Alon Gubkin
Alon Gubkin

Reputation: 57129

Is there a style selector in jQuery?

If I want to select every image which it's alt is Home for example, I can do something like this:

$("img[alt='Home']")

But how can I select every elements which their width CSS property is 750px for example in a single selector?

EDIT: If there is no such selector, is there any plugin, or any plans to do it in the next jQuery versions?

Upvotes: 15

Views: 19590

Answers (5)

Erutan409
Erutan409

Reputation: 752

This is an old one, but thanks to Jonathan del Strother's answer, it got me thinking on how to round this out a bit more:

(function($){

    // Add commonly used regex to the jQuery object
    var regex = {
        digits: /^(-?\d+(?:\.\d+)?)([a-zA-Z]+)?$/
        ,expr: /^([\w-]+)\s*([:=<>])\s*([\w-\.]+(?:\([^\)]+\))?)$/
    };

    // Create a custom jQuery function that allows a bit more useful CSS extraction
    $.fn.extend({
        cssExtract: function(cssAttr) {

            var val = {prop:this.css(cssAttr)};

            if (typeof val.prop === "string") {
                var match = regex.digits.exec(val.prop);
                if (match) {
                    val.int = Number(match[1]);
                    val.metric = match[2] || "px"
                }
            }

            return val;

        }
    });

    // Create the custom style selector
    $.find.selectors[":"].style = function(el, pos, match) {

        var search = regex.expr.exec(match[3]);

        if (search) {

            var style = search[1]
                ,operator = search[2]
                ,val = search[3]
                ,target = $(el).cssExtract(style)
                ,compare = (function(result){

                if (result) {
                    return {
                        int: Number(result[1])
                        ,metric: result[2] || "px"
                    };
                }

                return null;

            })(regex.digits.exec(val));

            if (
                target.metric
                && compare && compare.metric
                && target.metric === compare.metric
            ) {

                if (operator === "=" || operator === ":") {
                    return target.int === compare.int;
                } else if (operator === "<") {
                    return target.int < compare.int;
                } else if (operator === ">") {
                    return target.int > compare.int;
                }

            } else if (target.prop && (operator === "=" || operator === ":")) {
                return target.prop === val;
            }

        }

        return false;

    };

})(jQuery);

You should now be able to easily query with the custom style selector as follows:

$("div:style(height=57)")

At the time of this answer - should return the top div elements of Stack Overflow (this page).

Something like this will even work:

$("h3:style(color:rgb(106, 115, 124))")

Try adding the code in the developer tools in your browser. I tested it in Chrome. Haven't tested it in others. I also didn't put too much work into researching other pre-existing libraries/plugin's out there.

Upvotes: 1

Mike
Mike

Reputation: 66

I had a similar issue. Ended up writing a plugin to select elements based on their computed style.

https://github.com/MikeCostello/query-declaration

jQuery
$(":style({ width: 750px})")

Upvotes: 0

karim79
karim79

Reputation: 342665

var $images = $("img").filter(function() {
    return $(this).css('width') == '750px';
});

EDIT: There is no plugin I am aware of, or any plans to include such specific functionality. You can easily pluginify it yourself, such as (untested):

$.fn.filterByWidth = function(width) {
    var $images = $("img").filter(function() {
        return $(this).css('width') == width;
    });
    return $images;
};

Usage:

$images = $('#div img').filterByWidth('750px');
$images = $('#div img').filterByWidth('50%');
...etc...

Upvotes: 15

Jonathan del Strother
Jonathan del Strother

Reputation: 2572

Not necessarily a great idea, but you could add a new Sizzle selector for it :

$.expr[':'].width = function(elem, pos, match) {
    return $(elem).width() == parseInt(match[3]);
}

which you could then use like so:

$('div:width(970)')

That's going to be horrifically slow, though, so you'd want to narrow down on the number of elements you're comparing with something like :

$('#navbar>div:width(970)')

to only select those divs that are direct descendants of the navbar, which also have a width of 970px.

Upvotes: 17

Powerlord
Powerlord

Reputation: 88806

I have no idea if this will work, but...:

${"[style*=width: 750px]")

However, you might be better off using a class to control the width, then modifying the width of all instances of that class... or changing to a different class:

$(".classname").removeClass("classname").addClass("otherclassname");

Upvotes: 5

Related Questions