]> source.dussan.org Git - jquery.git/commitdiff
Fix #13434: native-API selector module
authorRichard Gibson <richard.gibson@gmail.com>
Tue, 19 Feb 2013 04:52:29 +0000 (23:52 -0500)
committerDave Methvin <dave.methvin@gmail.com>
Thu, 28 Feb 2013 03:45:55 +0000 (22:45 -0500)
What's out:
* 6 KB
* attribute not equal selector
* positional selectors (:first; :eq(n); :odd; etc.)
* type selectors (:input; :checkbox; :button; etc.)
* state-based selectors (:animated; :visible; :hidden; etc.)
* :has(selector)
* custom selectors
* leading combinators (e.g., $collection.find("> *"))
* reliable functionality on XML fragments
* requiring all parts of a selector to match elements under context (e.g., $div.find("div > *") now matches children of $div)
* matching against non-elements
* reliable sorting of disconnected nodes

Gruntfile.js
src/selector-native.js [new file with mode: 0644]

index f202ac8fe78677e06b90f1a3e1f34db36ed69389..7ff43035e2594d6e9182441679a09c75ce60f4d4 100644 (file)
@@ -22,7 +22,7 @@ module.exports = function( grunt ) {
                        files: distpaths
                },
                selector: {
-                       destFile: "src/selector.js",
+                       destFile: "src/selector-sizzle.js",
                        apiFile: "src/sizzle-jquery.js",
                        srcFile: "src/sizzle/sizzle.js"
                },
@@ -39,10 +39,9 @@ module.exports = function( grunt ) {
                                        "src/queue.js",
                                        "src/attributes.js",
                                        "src/event.js",
-                                       "src/selector.js",
+                                       { flag: "sizzle", src: "src/selector-sizzle.js", alt: "src/selector-native.js" },
                                        "src/traversing.js",
                                        "src/manipulation.js",
-
                                        { flag: "css", src: "src/css.js" },
                                        "src/serialize.js",
                                        { flag: "event-alias", src: "src/event-alias.js" },
@@ -145,8 +144,7 @@ module.exports = function( grunt ) {
                });
        });
 
-       // Build src/selector.js
-       grunt.registerTask( "selector", "Build src/selector.js", function() {
+       grunt.registerTask( "selector", "Build Sizzle-based selector module", function() {
 
                var cfg = grunt.config("selector"),
                        name = cfg.destFile,
@@ -190,7 +188,7 @@ module.exports = function( grunt ) {
                // Rejoin the pieces
                compiled = parts.join("");
 
-               grunt.verbose.write("Injected sizzle-jquery.js into sizzle.js");
+               grunt.verbose.writeln("Injected " + cfg.apiFile + " into " + cfg.srcFile);
 
                // Write concatenated source to file, and ensure newline-only termination
                grunt.file.write( name, compiled.replace( /\x0d\x0a/g, "\x0a" ) );
@@ -328,37 +326,47 @@ module.exports = function( grunt ) {
                                var flag = filepath.flag,
                                                specified = false,
                                                omit = false,
-                                               message = "";
+                                               messages = [];
 
                                if ( flag ) {
                                        if ( excluded[ flag ] !== undefined ) {
-                                               message = ( "Excluding " + flag ).red;
+                                               messages.push([
+                                                       ( "Excluding " + flag ).red,
+                                                       ( "(" + filepath.src + ")" ).grey
+                                               ]);
                                                specified = true;
-                                               omit = true;
-                                       } else {
-                                               message = ( "Including " + flag ).green;
+                                               omit = !filepath.alt;
+                                               if ( !omit ) {
+                                                       flag += " alternate";
+                                                       filepath.src = filepath.alt;
+                                               }
+                                       }
+                                       if ( excluded[ flag ] === undefined ) {
+                                               messages.push([
+                                                       ( "Including " + flag ).green,
+                                                       ( "(" + filepath.src + ")" ).grey
+                                               ]);
 
                                                // If this module was actually specified by the
-                                               // builder, then st the flag to include it in the
+                                               // builder, then set the flag to include it in the
                                                // output list
                                                if ( modules[ "+" + flag ] ) {
                                                        specified = true;
                                                }
                                        }
 
+                                       filepath = filepath.src;
+
                                        // Only display the inclusion/exclusion list when handling
                                        // an explicit list.
                                        //
                                        // Additionally, only display modules that have been specified
                                        // by the user
                                        if ( explicit && specified ) {
-                                               grunt.log.writetableln([ 27, 30 ], [
-                                                       message,
-                                                       ( "(" + filepath.src + ")").grey
-                                               ]);
+                                               messages.forEach(function( message ) {
+                                                       grunt.log.writetableln( [ 27, 30 ], message );
+                                               });
                                        }
-
-                                       filepath = filepath.src;
                                }
 
                                if ( !omit ) {
diff --git a/src/selector-native.js b/src/selector-native.js
new file mode 100644 (file)
index 0000000..11bf325
--- /dev/null
@@ -0,0 +1,125 @@
+var selector_hasDuplicate,
+       matches = docElem.matchesSelector ||
+               docElem.mozMatchesSelector ||
+               docElem.webkitMatchesSelector ||
+               docElem.oMatchesSelector ||
+               docElem.msMatchesSelector,
+       selector_sortOrder = function( a, b ) {
+               // Flag for duplicate removal
+               if ( a === b ) {
+                       selector_hasDuplicate = true;
+                       return 0;
+               }
+
+               var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b );
+
+               if ( compare ) {
+                       // Disconnected nodes
+                       if ( compare & 1 ) {
+
+                               // Choose the first element that is related to our document
+                               if ( a === document || jQuery.contains(document, a) ) {
+                                       return -1;
+                               }
+                               if ( b === document || jQuery.contains(document, b) ) {
+                                       return 1;
+                               }
+
+                               // Maintain original order
+                               return 0;
+                       }
+
+                       return compare & 4 ? -1 : 1;
+               }
+
+               // Not directly comparable, sort on existence of method
+               return a.compareDocumentPosition ? -1 : 1;
+       };
+
+jQuery.extend({
+       find: function( selector, context, results, seed ) {
+               var elem,
+                       i = 0;
+
+               results = results || [];
+               context = context || document;
+
+               if ( seed ) {
+                       while ( (elem = seed[i++]) ) {
+                               if ( jQuery.find.matchesSelector(elem, selector) ) {
+                                       results.push( elem );
+                               }
+                       }
+               } else {
+                       jQuery.merge( results, context.querySelectorAll(selector) );
+               }
+
+               return results;
+       },
+       unique: function( results ) {
+               var elem,
+                       duplicates = [],
+                       i = 0,
+                       j = 0;
+
+               selector_hasDuplicate = false;
+               results.sort( selector_sortOrder );
+
+               if ( selector_hasDuplicate ) {
+                       while ( (elem = results[i++]) ) {
+                               if ( elem === results[ i ] ) {
+                                       j = duplicates.push( i );
+                               }
+                       }
+                       while ( j-- ) {
+                               results.splice( duplicates[ j ], 1 );
+                       }
+               }
+
+               return results;
+       },
+       text: function( elem ) {
+               var node,
+                       ret = "",
+                       i = 0,
+                       nodeType = elem.nodeType;
+
+               if ( !nodeType ) {
+                       // If no nodeType, this is expected to be an array
+                       while ( (node = elem[i++]) ) {
+                               // Do not traverse comment nodes
+                               ret += jQuery.text( node );
+                       }
+               } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+                       // Use textContent for elements
+                       return elem.textContent;
+               } else if ( nodeType === 3 || nodeType === 4 ) {
+                       return elem.nodeValue;
+               }
+               // Do not include comment or processing instruction nodes
+
+               return ret;
+       },
+       contains: function( a, b ) {
+               var adown = a.nodeType === 9 ? a.documentElement : a,
+                       bup = b && b.parentNode;
+               return a === bup || !!( bup && bup.nodeType === 1 && adown.contains(bup) );
+       },
+       isXMLDoc: function( elem ) {
+               return (elem.ownerDocument || elem).documentElement.nodeName !== "HTML";
+       },
+       expr: {
+               match: {
+                       needsContext: /^[\x20\t\r\n\f]*[>+~]/
+               }
+       }
+});
+
+jQuery.extend( jQuery.find, {
+       matches: function( expr, elements ) {
+               return jQuery.find( expr, null, null, elements );
+       },
+       matchesSelector: function( elem, expr ) {
+               return matches.call( elem, expr );
+       }
+});