aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Gibson <richard.gibson@gmail.com>2013-02-18 23:52:29 -0500
committerDave Methvin <dave.methvin@gmail.com>2013-02-27 22:45:55 -0500
commit1083f82d1ee0c8f15a66be15e6184294a69d4420 (patch)
tree8e8571a87f4c4a3de06225442a674eeab6cd5420
parent0618710913f41d7a7f4c095f0edda035e65a887d (diff)
downloadjquery-1083f82d1ee0c8f15a66be15e6184294a69d4420.tar.gz
jquery-1083f82d1ee0c8f15a66be15e6184294a69d4420.zip
Fix #13434: native-API selector module
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
-rw-r--r--Gruntfile.js44
-rw-r--r--src/selector-native.js125
2 files changed, 151 insertions, 18 deletions
diff --git a/Gruntfile.js b/Gruntfile.js
index f202ac8fe..7ff43035e 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -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
index 000000000..11bf32507
--- /dev/null
+++ b/src/selector-native.js
@@ -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 );
+ }
+});