Side navigation
#312 closed enhancement (fixed)
Opened October 26, 2006 03:02AM UTC
Closed December 23, 2006 04:59PM UTC
Last modified June 19, 2007 07:11AM UTC
Parse By Style patch
| Reported by: | yehuda | Owned by: | |
|---|---|---|---|
| Priority: | minor | Milestone: | 1.1a |
| Component: | core | Version: | 1.1a |
| Keywords: | parser, selector, style | Cc: | |
| Blocked by: | Blocking: |
Description
This patch allows you use the regular jQuery function to parse by styles.
For example, you could do:
$("div[&display=inline]")
$("div[&height>=12]")
$("table[&border-collapse=collapse]")
The patch also slightly modifies the jQuery parsing system to make it more amenable to adding parsers:
Index: jquery.js
===================================================================
--- jquery.js (revision 475)
+++ jquery.js (working copy)
@@ -1637,8 +1637,24 @@
"^=": "z && !z.indexOf(m[4])",
"$=": "z && z.substr(z.length - m[4].length,m[4].length)==m[4]",
"*=": "z && z.indexOf(m[4])>=0",
- "": "z"
+ "": "z",
+ _resort: true,
+ _prefix: "z=jQuery.curCSS(a,m[3]);"
},
+ "&": {
+ "=": "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]);"
+ },
"[": "jQuery.find(m[2],a).length"
},
@@ -1917,7 +1933,10 @@
},
// The regular expressions that power the parsing engine
- parse: [
+ parse: [
+ // Match: [&value='test'], [&foo]
+ "\\[ *(&)S *([!*$^=<>]*) *('?"?)(.*?)\\4 *\\]",
+
// Match: [@value='test'], [@foo]
"\\[ *(@)S *([!*$^=]*) *('?"?)(.*?)\\4 *\\]",
@@ -1931,62 +1950,62 @@
"([:.#]*)S"
],
- 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
- if ( !i )
- 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
- eval("f = function(a,i){" +
- ( m[1] == "@" ? "z=jQuery.attr(a,m[3]);" : "" ) +
- "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 };
- },
-
+ 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
+ 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
+ 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 };
+ },
+
/**
* Remove the whitespace from the beginning and end of a string.
*
Attachments (1)
Change History (5)
Changed October 26, 2006 03:06AM UTC by comment:1
Changed October 27, 2006 05:08AM UTC by comment:2
Another patch, which adds the ability to easily add additional parsing engines, is at: http://www.visualjquery.com/patches/jquery.js.patch2
It increases the size of the packed jQuery by a total of 43 bytes
Changed November 01, 2006 05:00PM UTC by comment:3
This is nice. I can so see using this. My vote is for inclusion in the core. Great job yehuda!
Changed November 17, 2006 09:31PM UTC by comment:4
| description: | This patch allows you use the regular jQuery function to parse by styles.\ \ For example, you could do:\ $("div[&display=inline]")\ $("div[&height>=12]")\ $("table[&border-collapse=collapse]")\ \ The patch also slightly modifies the jQuery parsing system to make it more amenable to adding parsers:\ \ \ Index: jquery.js\ ===================================================================\ --- jquery.js (revision 475)\ +++ jquery.js (working copy)\ @@ -1637,8 +1637,24 @@\ "^=": "z && !z.indexOf(m[4])",\ "$=": "z && z.substr(z.length - m[4].length,m[4].length)==m[4]",\ "*=": "z && z.indexOf(m[4])>=0",\ - "": "z"\ + "": "z",\ + _resort: true,\ + _prefix: "z=jQuery.curCSS(a,m[3]);"\ },\ + "&": {\ + "=": "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]);"\ + },\ "[": "jQuery.find(m[2],a).length"\ },\ \ @@ -1917,7 +1933,10 @@\ },\ \ // The regular expressions that power the parsing engine\ - parse: [\ + parse: [ \ + // Match: [&value='test'], [&foo]\ + "\\[ *(&)S *([!*$^=<>]*) *('?"?)(.*?)\\4 *\\]",\ + \ // Match: [@value='test'], [@foo]\ "\\[ *(@)S *([!*$^=]*) *('?"?)(.*?)\\4 *\\]",\ \ @@ -1931,62 +1950,62 @@\ "([:.#]*)S"\ ],\ \ - 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\ - if ( !i )\ - 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\ - eval("f = function(a,i){" +\ - ( m[1] == "@" ? "z=jQuery.attr(a,m[3]);" : "" ) +\ - "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 };\ - },\ -\ + 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\ + 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\ + 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 };\ + },\ + \ /**\ * Remove the whitespace from the beginning and end of a string.\ *\ → This patch allows you use the regular jQuery function to parse by styles.\ \ For example, you could do:\ {{{\ $("div[&display=inline]") \ $("div[&height>=12]")\ $("table[&border-collapse=collapse]")\ }}}\ \ The patch also slightly modifies the jQuery parsing system to make it more amenable to adding parsers:\ \ {{{\ Index: jquery.js\ ===================================================================\ --- jquery.js (revision 475)\ +++ jquery.js (working copy)\ @@ -1637,8 +1637,24 @@\ "^=": "z && !z.indexOf(m[4])",\ "$=": "z && z.substr(z.length - m[4].length,m[4].length)==m[4]",\ "*=": "z && z.indexOf(m[4])>=0",\ - "": "z"\ + "": "z",\ + _resort: true,\ + _prefix: "z=jQuery.curCSS(a,m[3]);"\ },\ + "&": {\ + "=": "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]);"\ + },\ "[": "jQuery.find(m[2],a).length"\ },\ \ @@ -1917,7 +1933,10 @@\ },\ \ // The regular expressions that power the parsing engine\ - parse: [\ + parse: [ \ + // Match: [&value='test'], [&foo]\ + "\\[ *(&)S *([!*$^=<>]*) *('?"?)(.*?)\\4 *\\]",\ + \ // Match: [@value='test'], [@foo]\ "\\[ *(@)S *([!*$^=]*) *('?"?)(.*?)\\4 *\\]",\ \ @@ -1931,62 +1950,62 @@\ "([:.#]*)S"\ ],\ \ - 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\ - if ( !i )\ - 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\ - eval("f = function(a,i){" +\ - ( m[1] == "@" ? "z=jQuery.attr(a,m[3]);" : "" ) +\ - "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 };\ - },\ -\ + 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\ + 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\ + 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 };\ + },\ + \ /**\ * Remove the whitespace from the beginning and end of a string.\ *\ }}} |
|---|---|
| milestone: | → 1.1 |
| priority: | major → minor |
| version: | → 1.1 |
Changed December 23, 2006 04:59PM UTC by comment:5
| resolution: | → fixed |
|---|---|
| status: | new → closed |
The changes have been added to SVN (rev 774) so that you can write the select-by-style selectors as a plugin. The only change is that _resort(m) is a function that takes the match array and reorganizes (as opposed to a boolean value).
The patch is at: http://www.visualjquery.com/patches/jquery.js.patch