The plugin is below:

/**
 * The current filter method hardcodes in the first RegExp for special behavior.
 * Specifically, it gets a special sort order and has code that needs to be executed
 * prior to executing the code for individual comparison operators.
 *
 * The new code adds special _resort and _prefix properties for the objects used
 * in jQuery.expr. The _resort property is a boolean value that simply indicates
 * whether the array returned by the parser needs to be resorted.
 *
 * The filter method tries to do expr[m[1]][m[2]], while means that the array needs
 * to have "@" or "&" in m[1] and "=", "!=" or ">=" in m[2] to work correctly.
 *
 * The _resort property tells the filter method to resort the array in accordance
 * with the rule sthe parser originally used for attribute selectors.
 *
 * The _prefix property allows you to specify code that needs to be executed before
 * the code for specific operators.
 *
 * The attribute selectors originally executed z=jQuery.attr(a,m[3]); which gives
 * the individual operators access to the simple z variable to use in the individual
 * code. Adding _prefix allows me to execute z=jQuery.curCSS(a,m[3]); before the
 * code in the individual selectors.
 *
 * I added the >, <, >=, <= comparisons to the style selectors, which simply run
 * parseInt on both z and m[4].
 *
 */

jQuery.parse.unshift(
    // Match: [&value='test'], [&foo]
    "\\[ *(&)S *([!*$^=<>]*) *('?\"?)(.*?)\\4 *\\]"
)

// Apply the _resort and _prefix properties to @
jQuery.expr["@"]["_resort"] = true;
jQuery.expr["@"]["_prefix"] = "z=jQuery.attr(a,m[3]);";

// Make "&" follow the same rules as "@"
jQuery.expr["&"] = {
        "=": "z==m[4]",
        "!=": "z!=m[4]",
        "^=": "z && !z.indexOf(m[4])",
        "$=": "z && z.substr(z.length - m[4].length,m[4].length)==m[4]",
        "*=": "z && z.indexOf(m[4])>=0",
    ">": "parseInt(z)>parseInt(m[4])",
    "<": "parseInt(z)<parseInt(m[4])",
    ">=": "parseInt(z)>=parseInt(m[4])",
    "<=": "parseInt(z)<=parseInt(m[4])",
        "": "z",
    _resort: true,
    _prefix: "z= jQuery.curCSS(a,m[3]);"
    }

// Make changes to jQuery.filter
jQuery.filter = function(t,r,not) {
    // Figure out if we're doing regular, or inverse, filtering
    var g = not !== false ? jQuery.grep :
        function(a,f) {return jQuery.grep(a,f,true);};

    while ( t && /^[a-z[({<*:.#]/i.test(t) ) {

        var p = jQuery.parse;

        for ( var i = 0; i < p.length; i++ ) {
   
            // Look for, and replace, string-like sequences
            // and finally build a regexp out of it
            var re = new RegExp(
                "^" + p[i].replace("S", "([a-z*_-][a-z0-9_-]*)"), "i" );

            var m = re.exec( t );

            if ( m ) {
                // Re-organize the first match
        // [[CHANGE]] Check for the _resort property on the expr
                if ( jQuery.expr [m[1]]["_resort"] )
                    m = ["",m[1], m[3], m[2], m[5]];

                // Remove what we just matched
                t = t.replace( re, "" );

                break;
            }
        }

        // :not() is a special case that can be optimized by
        // keeping it out of the _expression_ list
        if ( m[1] == ":" && m[2] == "not" )
            r = jQuery.filter(m[3],r,false).r;

        // Otherwise, find the _expression_ to execute
        else {
            var f = jQuery.expr[m[1]];
            if ( f.constructor != String )
                f = jQuery.expr[m[1]][m[2]];

            // Build a custom macro to enclose it
      // [[CHANGE]] Allow for optional prefixes
            eval("f = function(a,i){" +
                (jQuery.expr[m[1]]["_prefix"] || "") +
                "return " + f + "}");

            // Execute it against the current filter
            r = g( r, f );
        }
    }

    // Return an array of filtered elements (r)
    // and the modified _expression_ string (t)
    return { r: r, t: t };
};


On 10/25/06, Yehuda Katz < [EMAIL PROTECTED]> wrote:
I wrote a plugin that extends the jQuery parser to allow for selecting elements by current computed CSS. Stuff like:

$("div[&display=inline]")
$("div[&height>100]")
$("div[&min-height]")

The syntax is exactly the same as for attribute selectors, except that you can also do numeric comparisons for CSS attributes that begin with a number. For the >, <, >=, and <= comparisons, the plugin just does a parseInt on both the CSS property and what you pass in, so $("div[height>100px]") is the same as $("div[height>100"). It will match elements with heights bigger than 100px or 100em (so be careful about that if you use the comparison operators).

For those who are interested in how I did it, I made some minor modifications to the existing filter method, which does the parsing. Specifically:

* I added a _resort property to the objects in jQuery.expr , which is a boolean value that returns true if the array returned by the parser RegExp needs to be resorted (that's required by parsers that utilize operators like =, !=, and ^=). The jQuery source currently hardcodes in just the existing attribute RegExp, which means I couldn't implement the [&style=whatever].
* I added a _prefix property to the objects in jQuery.expr, which is code that will be executed before the code for each selector. Previously, jQuery hardcoded in the prefix code for the attribute selector.
* I replaced the hardcoded in stuff in the filter method to use the new _prefix and _resort properties.

I'm going to be submitting a patch to jQuery proper, but in the meantime, you can use the new parse by style selectors.

--
Yehuda Katz
Web Developer | Wycats Designs
(ph)  718.877.1325




--
Yehuda Katz
Web Developer | Wycats Designs
(ph)  718.877.1325
_______________________________________________
jQuery mailing list
[email protected]
http://jquery.com/discuss/

Reply via email to