From 825ac3773694e0cd23ee74895fd5aeb535b27da4 Mon Sep 17 00:00:00 2001 From: Timmy Willison Date: Mon, 9 Sep 2013 19:13:01 -0500 Subject: [PATCH] Separate jQuery.fn.init into its own module (for lighter core dependencies across all modules) --- src/ajax.js | 1 + src/attributes/classes.js | 3 +- src/attributes/val.js | 3 +- src/core.js | 117 +------------------------- src/core/init.js | 123 ++++++++++++++++++++++++++++ src/core/parseHTML.js | 2 +- src/core/ready.js | 1 + src/{ => core}/var/rsingleTag.js | 0 src/css.js | 1 + src/effects.js | 1 + src/event.js | 1 + src/manipulation.js | 1 + src/offset.js | 1 + src/serialize.js | 1 + src/traversing.js | 100 ++-------------------- src/traversing/findFilter.js | 100 ++++++++++++++++++++++ src/traversing/var/rneedsContext.js | 6 ++ src/wrap.js | 1 + 18 files changed, 250 insertions(+), 213 deletions(-) create mode 100644 src/core/init.js rename src/{ => core}/var/rsingleTag.js (100%) create mode 100644 src/traversing/findFilter.js create mode 100644 src/traversing/var/rneedsContext.js diff --git a/src/ajax.js b/src/ajax.js index c1468a734..364e5a4b6 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -3,6 +3,7 @@ define([ "./var/rnotwhite", "./ajax/var/nonce", "./ajax/var/rquery", + "./core/init", "./ajax/parseJSON", "./ajax/parseXML", "./deferred" diff --git a/src/attributes/classes.js b/src/attributes/classes.js index aed8db88a..d7212f9de 100644 --- a/src/attributes/classes.js +++ b/src/attributes/classes.js @@ -2,7 +2,8 @@ define([ "../core", "../var/rnotwhite", "../var/strundefined", - "../data/var/data_priv" + "../data/var/data_priv", + "../core/init" ], function( jQuery, rnotwhite, strundefined, data_priv ) { var rclass = /[\t\r\n\f]/g; diff --git a/src/attributes/val.js b/src/attributes/val.js index 74d8c9c46..0e7e7ce43 100644 --- a/src/attributes/val.js +++ b/src/attributes/val.js @@ -1,6 +1,7 @@ define([ "../core", - "./support" + "./support", + "../core/init" ], function( jQuery, support ) { var rreturn = /\r/g; diff --git a/src/core.js b/src/core.js index 3cdcc63af..599caba64 100644 --- a/src/core.js +++ b/src/core.js @@ -10,12 +10,8 @@ var toString = require( "./var/toString" ), hasOwn = require( "./var/hasOwn" ), trim = require( "./var/trim" ), - rsingleTag = require( "./var/rsingleTag" ), support = require( "./var/support" ), - // A central reference to the root jQuery(document) - rootjQuery, - // Use the correct document accordingly with window argument (sandbox) document = window.document, @@ -30,14 +26,10 @@ var // Define a local copy of jQuery jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context, rootjQuery ); + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); }, - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, - // Matches dashed string for camelizing rmsPrefix = /^-ms-/, rdashAlpha = /-([\da-z])/gi, @@ -53,105 +45,6 @@ jQuery.fn = jQuery.prototype = { constructor: jQuery, - init: function( selector, context, rootjQuery ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - - // scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[1], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - // Properties of context are called as methods if possible - if ( jQuery.isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || rootjQuery ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return typeof rootjQuery.ready !== "undefined" ? - rootjQuery.ready( selector ) : - // Execute immediately if ready is not present - selector( jQuery ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }, - // Start with an empty selector selector: "", @@ -231,9 +124,6 @@ jQuery.fn = jQuery.prototype = { splice: arr.splice }; -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, @@ -621,8 +511,5 @@ function isArraylike( obj ) { typeof length === "number" && length > 0 && ( length - 1 ) in obj ); } -// All jQuery objects should point back to these -rootjQuery = jQuery( document ); - return jQuery; }); diff --git a/src/core/init.js b/src/core/init.js new file mode 100644 index 000000000..e349bb616 --- /dev/null +++ b/src/core/init.js @@ -0,0 +1,123 @@ +// Initialize a jQuery object +define([ + "../core", + "./var/rsingleTag", + "../traversing/findFilter" +], function( jQuery, rsingleTag ) { + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + init = jQuery.fn.init = function( selector, context ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return typeof rootjQuery.ready !== "undefined" ? + rootjQuery.ready( selector ) : + // Execute immediately if ready is not present + selector( jQuery ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + +return init; + +}); diff --git a/src/core/parseHTML.js b/src/core/parseHTML.js index 15e3e512f..64cf2a18a 100644 --- a/src/core/parseHTML.js +++ b/src/core/parseHTML.js @@ -1,6 +1,6 @@ define([ "../core", - "../var/rsingleTag", + "./var/rsingleTag", "../manipulation" // buildFragment ], function( jQuery, rsingleTag ) { diff --git a/src/core/ready.js b/src/core/ready.js index 2e33781c2..e64977cd9 100644 --- a/src/core/ready.js +++ b/src/core/ready.js @@ -1,5 +1,6 @@ define([ "../core", + "../core/init", "../deferred" ], function( jQuery ) { diff --git a/src/var/rsingleTag.js b/src/core/var/rsingleTag.js similarity index 100% rename from src/var/rsingleTag.js rename to src/core/var/rsingleTag.js diff --git a/src/css.js b/src/css.js index a80d1c3b8..244fd683e 100644 --- a/src/css.js +++ b/src/css.js @@ -29,6 +29,7 @@ var cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; // Dependencies not needed as vars +require( "./core/init" ); require( "./css/swap" ); require( "./core/ready" ); require( "./selector" ); // contains diff --git a/src/effects.js b/src/effects.js index 2196d9bc7..e61e576cb 100644 --- a/src/effects.js +++ b/src/effects.js @@ -63,6 +63,7 @@ var }; // Dependencies not needed as vars +require( "./core/init" ); require( "./effects/Tween" ); require( "./queue" ); require( "./css" ); diff --git a/src/event.js b/src/event.js index 6887b36dd..866e4f0dd 100644 --- a/src/event.js +++ b/src/event.js @@ -14,6 +14,7 @@ var rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; // Dependencies not needed as vars +require( "./core/init" ); require( "./data/accepts" ); require( "./selector" ); diff --git a/src/manipulation.js b/src/manipulation.js index 35a5996d7..d8b45528c 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -42,6 +42,7 @@ wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.the wrapMap.th = wrapMap.td; // Dependencies not needed as variables +require( "./core/init" ); require( "./data/accepts" ); require( "./traversing" ); require( "./selector" ); diff --git a/src/offset.js b/src/offset.js index fc63be731..b53524b76 100644 --- a/src/offset.js +++ b/src/offset.js @@ -2,6 +2,7 @@ define([ "./core", "./var/strundefined", "./core/access", + "./core/init", "./css", "./selector" // contains ], function( jQuery, strundefined, access ) { diff --git a/src/serialize.js b/src/serialize.js index 85798ef62..797d735aa 100644 --- a/src/serialize.js +++ b/src/serialize.js @@ -1,6 +1,7 @@ define([ "./core", "./manipulation/var/rcheckableType", + "./core/init", "./traversing", // filter "./attributes/prop" ], function( jQuery, rcheckableType ) { diff --git a/src/traversing.js b/src/traversing.js index b66a22f6d..4e55c8257 100644 --- a/src/traversing.js +++ b/src/traversing.js @@ -1,12 +1,13 @@ define([ "./core", "./var/indexOf", + "./traversing/var/rneedsContext", + "./core/init", + "./traversing/findFilter", "./selector" -], function( jQuery, indexOf ) { +], function( jQuery, indexOf, rneedsContext ) { -var isSimple = /^.[^:#\[\.,]*$/, - rparentsprev = /^(?:parents|prev(?:Until|All))/, - rneedsContext = jQuery.expr.match.needsContext, +var rparentsprev = /^(?:parents|prev(?:Until|All))/, // methods guaranteed to produce a unique set when starting from a unique set guaranteedUnique = { children: true, @@ -15,51 +16,7 @@ var isSimple = /^.[^:#\[\.,]*$/, prev: true }; -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - /* jshint -W018 */ - return !!qualifier.call( elem, i, elem ) !== not; - }); - - } - - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - }); - - } - - if ( typeof qualifier === "string" ) { - if ( isSimple.test( qualifier ) ) { - return jQuery.filter( qualifier, elements, not ); - } - - qualifier = jQuery.filter( qualifier, elements ); - } - - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) >= 0 ) !== not; - }); -} - jQuery.extend({ - filter: function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 && elem.nodeType === 1 ? - jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : - jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - })); - }, - dir: function( elem, dir, until ) { var matched = [], truncate = until !== undefined; @@ -89,32 +46,6 @@ jQuery.extend({ }); jQuery.fn.extend({ - find: function( selector ) { - var i, - ret = [], - self = this, - len = self.length; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter(function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - }) ); - } - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - // Needed because $( selector, context ) becomes $( context ).find( selector ) - ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); - ret.selector = this.selector ? this.selector + " " + selector : selector; - return ret; - }, - has: function( target ) { var targets = jQuery( target, this ), l = targets.length; @@ -129,27 +60,6 @@ jQuery.fn.extend({ }); }, - not: function( selector ) { - return this.pushStack( winnow(this, selector || [], true) ); - }, - - filter: function( selector ) { - return this.pushStack( winnow(this, selector || [], false) ); - }, - - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - }, - closest: function( selectors, context ) { var cur, i = 0, diff --git a/src/traversing/findFilter.js b/src/traversing/findFilter.js new file mode 100644 index 000000000..71fe52aaf --- /dev/null +++ b/src/traversing/findFilter.js @@ -0,0 +1,100 @@ +define([ + "../core", + "../var/indexOf", + "./var/rneedsContext", + "../selector" +], function( jQuery, indexOf, rneedsContext ) { + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) >= 0 ) !== not; + }); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +}); + +}); diff --git a/src/traversing/var/rneedsContext.js b/src/traversing/var/rneedsContext.js new file mode 100644 index 000000000..3d6ae4038 --- /dev/null +++ b/src/traversing/var/rneedsContext.js @@ -0,0 +1,6 @@ +define([ + "../../core", + "../../selector" +], function( jQuery ) { + return jQuery.expr.match.needsContext; +}); diff --git a/src/wrap.js b/src/wrap.js index a7a1a14c0..b6dce72e6 100644 --- a/src/wrap.js +++ b/src/wrap.js @@ -1,5 +1,6 @@ define([ "./core", + "./core/init", "./traversing" // parent, contents ], function( jQuery ) { -- 2.39.5