no1:
// define a local copy of jquery
var jquery = function( selector, context ) {
// the jquery object is actually just the init constructor 'enhanced'
return new jquery.fn.init( selector, context, rootjquery ); //調用第二步init方法
},
no2:
jquery.fn = jquery.prototype = {
constructor: jquery,
init: function( selector, context, rootjquery ) {
var match, elem, ret, doc;
// handle $(""), $(null), or $(undefined)
if ( !selector ) {
return this;
}
// handle $(domelement)
if ( selector.nodetype ) {
this.context = this[0] = selector;
this.length = 1;
// the body element only exists once, optimize finding it
if ( selector === "body" && !context && document.body ) {
this.context = document;
this[0] = document.body;
this.selector = selector;
// handle html strings
if ( typeof selector === "string" ) {
// are we dealing with html string or an id?
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 = quickexpr.exec( selector );
// verify a match, and that no context was specified for #id
if ( match && (match[1] || !context) ) {
// handle: $(html) -> $(array)
if ( match[1] ) {
context = context instanceof jquery ? context[0] : context;
doc = ( context ? context.ownerdocument || context : document );
// if a single string is passed in and it's a single tag
// just do a createelement and skip the rest
ret = rsingletag.exec( selector );
if ( ret ) {
if ( jquery.isplainobject( context ) ) {
selector = [ document.createelement( ret[1] ) ];
jquery.fn.attr.call( selector, context, true );
selector = [ doc.createelement( ret[1] ) ];
ret = jquery.buildfragment( [ match[1] ], [ doc ] );
selector = ( ret.cacheable ? jquery.clone(ret.fragment) : ret.fragment ).childnodes;
return jquery.merge( this, selector );
// handle: $("#id")
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 ) {
// handle the case where ie and opera return items
// by name instead of id
if ( elem.id !== match[2] ) {
return rootjquery.find( selector );
// otherwise, we inject the element directly into the jquery object
this[0] = elem;
// handle: $(expr, $(...))
} else if ( !context || context.jquery ) {
return ( context || rootjquery ).find( selector );
// handle: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
return this.constructor( context ).find( selector );
// handle: $(function)
// shortcut for document ready
} else if ( jquery.isfunction( selector ) ) {
return rootjquery.ready( selector );
if ( selector.selector !== undefined ) {
this.selector = selector.selector;
this.context = selector.context;
return jquery.makearray( selector, this );
// start with an empty selector
selector: "",
// the current version of jquery being used
jquery: "1.7.1",
// the default length of a jquery object is 0
length: 0,
// the number of elements contained in the matched element set
size: function() {
return this.length;
toarray: function() {
return slice.call( this, 0 );
// get the nth element in the matched element set or
// get the whole matched element set as a clean array
get: function( num ) {
return num == null ?
// return a 'clean' array
this.toarray() :
// return just the object
( num < 0 ? this[ this.length + num ] : this[ num ] );
// take an array of elements and push it onto the stack
// (returning the new matched element set)
pushstack: function( elems, name, selector ) {
// build a new jquery matched element set
var ret = this.constructor();
if ( jquery.isarray( elems ) ) {
push.apply( ret, elems );
jquery.merge( ret, elems );
// add the old object onto the stack (as a reference)
ret.prevobject = this;
ret.context = this.context;
if ( name === "find" ) {
ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
} else if ( name ) {
ret.selector = this.selector + "." + name + "(" + selector + ")";
// return the newly-formed element set
return ret;
// execute a callback for every element in the matched set.
// (you can seed the arguments with an array of args, but this is
// only used internally.)
each: function( callback, args ) {
return jquery.each( this, callback, args );
ready: function( fn ) {
// attach the listeners
jquery.bindready();
// add the callback
readylist.add( fn );
eq: function( i ) {
i = +i;
return i === -1 ?
this.slice( i ) :
this.slice( i, i + 1 );
first: function() {
return this.eq( 0 );
last: function() {
return this.eq( -1 );
slice: function() {
return this.pushstack( slice.apply( this, arguments ),
"slice", slice.call(arguments).join(",") );
map: function( callback ) {
return this.pushstack( jquery.map(this, function( elem, i ) {
return callback.call( elem, i, elem );
}));
end: function() {
return this.prevobject || this.constructor(null);
// for internal use only.
// behaves like an array's method, not like a jquery method.
push: push,
sort: [].sort,
splice: [].splice
};
no3: 進入append入口
jquery.fn.extend({
text: function( text ) {
if ( jquery.isfunction(text) ) {
return this.each(function(i) {
var self = jquery( this );
self.text( text.call(this, i, self.text()) );
});
if ( typeof text !== "object" && text !== undefined ) {
return this.empty().append( (this[0] && this[0].ownerdocument || document).createtextnode( text ) );
return jquery.text( this );
wrapall: function( html ) {
if ( jquery.isfunction( html ) ) {
jquery(this).wrapall( html.call(this, i) );
if ( this[0] ) {
// the elements to wrap the target around
var wrap = jquery( html, this[0].ownerdocument ).eq(0).clone(true);
if ( this[0].parentnode ) {
wrap.insertbefore( this[0] );
wrap.map(function() {
var elem = this;
while ( elem.firstchild && elem.firstchild.nodetype === 1 ) {
elem = elem.firstchild;
return elem;
}).append( this );
wrapinner: function( html ) {
jquery(this).wrapinner( html.call(this, i) );
return this.each(function() {
var self = jquery( this ),
contents = self.contents();
if ( contents.length ) {
contents.wrapall( html );
self.append( html );
wrap: function( html ) {
var isfunction = jquery.isfunction( html );
jquery( this ).wrapall( isfunction ? html.call(this, i) : html );
unwrap: function() {
return this.parent().each(function() {
if ( !jquery.nodename( this, "body" ) ) {
jquery( this ).replacewith( this.childnodes );
}).end();
append: function() {
if ( this.nodetype === 1 ) {
this.appendchild( elem );
prepend: function() {
return this.dommanip(arguments, true, function( elem ) {
this.insertbefore( elem, this.firstchild );
before: function() {
if ( this[0] && this[0].parentnode ) {
return this.dommanip(arguments, false, function( elem ) {
this.parentnode.insertbefore( elem, this );
} else if ( arguments.length ) {
var set = jquery.clean( arguments );
set.push.apply( set, this.toarray() );
return this.pushstack( set, "before", arguments );
after: function() {
this.parentnode.insertbefore( elem, this.nextsibling );
var set = this.pushstack( this, "after", arguments );
set.push.apply( set, jquery.clean(arguments) );
return set;
// keepdata is for internal use only--do not document
remove: function( selector, keepdata ) {
for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
if ( !selector || jquery.filter( selector, [ elem ] ).length ) {
if ( !keepdata && elem.nodetype === 1 ) {
jquery.cleandata( elem.getelementsbytagname("*") );
jquery.cleandata( [ elem ] );
if ( elem.parentnode ) {
elem.parentnode.removechild( elem );
empty: function() {
// remove element nodes and prevent memory leaks
if ( elem.nodetype === 1 ) {
// remove any remaining nodes
while ( elem.firstchild ) {
elem.removechild( elem.firstchild );
clone: function( dataandevents, deepdataandevents ) {
dataandevents = dataandevents == null ? false : dataandevents;
deepdataandevents = deepdataandevents == null ? dataandevents : deepdataandevents;
return this.map( function () {
return jquery.clone( this, dataandevents, deepdataandevents );
html: function( value ) {
if ( value === undefined ) {
return this[0] && this[0].nodetype === 1 ?
this[0].innerhtml.replace(rinlinejquery, "") :
null;
// see if we can take a shortcut and just use innerhtml
} else if ( typeof value === "string" && !rnoinnerhtml.test( value ) &&
(jquery.support.leadingwhitespace || !rleadingwhitespace.test( value )) &&
!wrapmap[ (rtagname.exec( value ) || ["", ""])[1].tolowercase() ] ) {
value = value.replace(rxhtmltag, "<$1></$2>");
try {
for ( var i = 0, l = this.length; i < l; i++ ) {
if ( this[i].nodetype === 1 ) {
jquery.cleandata( this[i].getelementsbytagname("*") );
this[i].innerhtml = value;
// if using innerhtml throws an exception, use the fallback method
} catch(e) {
this.empty().append( value );
} else if ( jquery.isfunction( value ) ) {
this.each(function(i){
self.html( value.call(this, i, self.html()) );
replacewith: function( value ) {
// make sure that the elements are removed from the dom before they are inserted
// this can help fix replacing a parent with child elements
if ( jquery.isfunction( value ) ) {
var self = jquery(this), old = self.html();
self.replacewith( value.call( this, i, old ) );
if ( typeof value !== "string" ) {
value = jquery( value ).detach();
var next = this.nextsibling,
parent = this.parentnode;
jquery( this ).remove();
if ( next ) {
jquery(next).before( value );
jquery(parent).append( value );
return this.length ?
this.pushstack( jquery(jquery.isfunction(value) ? value() : value), "replacewith", value ) :
this;
detach: function( selector ) {
return this.remove( selector, true );
dommanip: function( args, table, callback ) {
var results, first, fragment, parent,
value = args[0],
scripts = [];
// we can't clonenode fragments that contain checked, in webkit
if ( !jquery.support.checkclone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
jquery(this).dommanip( args, table, callback, true );
if ( jquery.isfunction(value) ) {
var self = jquery(this);
args[0] = value.call(this, i, table ? self.html() : undefined);
self.dommanip( args, table, callback );
parent = value && value.parentnode;
// if we're in a fragment, just use that instead of building a new one
if ( jquery.support.parentnode && parent && parent.nodetype === 11 && parent.childnodes.length === this.length ) {
results = { fragment: parent };
results = jquery.buildfragment( args, this, scripts ); //構造一個新執行個體
fragment = results.fragment;
if ( fragment.childnodes.length === 1 ) {
first = fragment = fragment.firstchild;
first = fragment.firstchild;
if ( first ) {
table = table && jquery.nodename( first, "tr" );
for ( var i = 0, l = this.length, lastindex = l - 1; i < l; i++ ) {
callback.call(
table ?
root(this[i], first) :
this[i],
// make sure that we do not leak memory by inadvertently discarding
// the original fragment (which might have attached data) instead of
// using it; in addition, use the original fragment object for the last
// item instead of first because it can end up being emptied incorrectly
// in certain situations (bug #8070).
// fragments from the fragment cache must always be cloned and never used
// in place.
results.cacheable || ( l > 1 && i < lastindex ) ?
jquery.clone( fragment, true, true ) :
fragment
);
if ( scripts.length ) {
jquery.each( scripts, evalscript );
//buildfragment 方法
jquery.buildfragment = function( args, nodes, scripts ) {
var fragment, cacheable, cacheresults, doc,
first = args[ 0 ];
// nodes may contain either an explicit document object,
// a jquery collection or context object.
// if nodes[0] contains a valid object to assign to doc
if ( nodes && nodes[0] ) {
doc = nodes[0].ownerdocument || nodes[0];
// ensure that an attr object doesn't incorrectly stand in as a document object
// chrome and firefox seem to allow this to occur and will throw exception
// fixes #8950
if ( !doc.createdocumentfragment ) {
doc = document;
// only cache "small" (1/2 kb) html strings that are associated with the main document
// cloning options loses the selected state, so don't cache them
// ie 6 doesn't like it when you put <object> or <embed> elements in a fragment
// also, webkit does not clone 'checked' attributes on clonenode, so don't cache
// lastly, ie6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
first.charat(0) === "<" && !rnocache.test( first ) &&
(jquery.support.checkclone || !rchecked.test( first )) &&
(jquery.support.html5clone || !rnoshimcache.test( first )) ) {
cacheable = true;
cacheresults = jquery.fragments[ first ];
if ( cacheresults && cacheresults !== 1 ) {
fragment = cacheresults;
if ( !fragment ) {
fragment = doc.createdocumentfragment();
jquery.clean( args, doc, fragment, scripts );
if ( cacheable ) {
jquery.fragments[ first ] = cacheresults ? fragment : 1;
return { fragment: fragment, cacheable: cacheable };