现在的位置: 首页 > 综合 > 正文

jquery原来是这么回事

2019年05月22日 ⁄ 综合 ⁄ 共 18727字 ⁄ 字号 评论关闭

JQuery总的来讲是一个包含若干属性的对象,通过extend进行扩展

var jQuery = (function() {

	// Define a local copy of jQuery
	var jQuery = function(selector, context) {
		return new jQuery.fn.init(selector, context, rootjQuery);//init方法是具有参数的
	},

	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,

	// Map over the $ in case of overwrite
	_$ = window.$,

	// A central reference to the root jQuery(document)
	rootjQuery,

	// A simple way to check for HTML strings or ID strings
	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
	quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,

	// Check if a string has a non-whitespace character in it
	rnotwhite = /\S/,

	// Used for trimming whitespace
	trimLeft = /^\s+/, trimRight = /\s+$/,

	// Match a standalone tag
	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,

	// JSON RegExp
	rvalidchars = /^[\],:{}\s]*$/, rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,

	// Useragent RegExp
	rwebkit = /(webkit)[ \/]([\w.]+)/, ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, rmsie = /(msie) ([\w.]+)/, rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,

	// Matches dashed string for camelizing
	rdashAlpha = /-([a-z]|[0-9])/ig, rmsPrefix = /^-ms-/,

	// Used by jQuery.camelCase as callback to replace()
	fcamelCase = function(all, letter) {
		return (letter + "").toUpperCase();
	},

	// Keep a UserAgent string for use with jQuery.browser
	userAgent = navigator.userAgent,

	// For matching the engine and version of the browser
	browserMatch,

	// The deferred used on DOM ready
	readyList,

	// The ready event handler
	DOMContentLoaded,

	// Save a reference to some core methods
	toString = Object.prototype.toString, hasOwn = Object.prototype.hasOwnProperty, push = Array.prototype.push, slice = Array.prototype.slice, trim = String.prototype.trim, indexOf = Array.prototype.indexOf,

	// [[Class]] -> type pairs
	class2type = {};

	//这才是最原始的jquery对象
	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;
				return this;
			}

			// 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;
				this.length = 1;
				return this;
			}

			// 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);

							} else {
								selector = [ doc.createElement(ret[1]) ];
							}

						} else {
							ret = jQuery.buildFragment([ match[1] ], [ doc ]);
							selector = (ret.cacheable ? jQuery
									.clone(ret.fragment) : ret.fragment).childNodes;
						}

						return jQuery.merge(this, selector);

						// 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) {
							// 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.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: $(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.2",

		// 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);

			} else {
				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);

			return this;
		},

		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
	};
	//此处向上是最原始的JQuery
	
	// Give the init function the jQuery prototype for later instantiation
	jQuery.fn.init.prototype = jQuery.fn;
	//使用jquery的原型来代替init.prototype,因为init.prototype只是生成了一个object
	
	//接下来是object的扩展方法
	//注意:arguments参数看成是一个动态参数,在函数的定义过程中可以不声明形参,在函数中通过arguments[X]获取
	jQuery.extend = jQuery.fn.extend = function() {
		var options, name, src, copy, copyIsArray, clone, target = arguments[0]
				|| {}, i = 1, length = arguments.length, deep = false;

		// Handle a deep copy situation
		if (typeof target === "boolean") {
			deep = target;
			target = arguments[1] || {};
			// skip the boolean and the target
			i = 2;
		}

		// Handle case when target is a string or something (possible in
		// deep copy)
		if (typeof target !== "object" && !jQuery.isFunction(target)) {
			target = {};
		}

		// extend jQuery itself if only one argument is passed
		if (length === i) {
			target = this;
			--i;
		}

		for (; i < length; i++) {
			// Only deal with non-null/undefined values
			if ((options = arguments[i]) != null) {
				// Extend the base object
				for (name in options) {
					src = target[name];
					copy = options[name];

					// Prevent never-ending loop
					if (target === copy) {
						continue;
					}

					// Recurse if we're merging plain objects or arrays
					if (deep
							&& copy
							&& (jQuery.isPlainObject(copy) || (copyIsArray = jQuery
									.isArray(copy)))) {
						if (copyIsArray) {
							copyIsArray = false;
							clone = src && jQuery.isArray(src) ? src : [];

						} else {
							clone = src && jQuery.isPlainObject(src) ? src : {};
						}

						// Never move original objects, clone them
						target[name] = jQuery.extend(deep, clone, copy);

						// Don't bring in undefined values
					} else if (copy !== undefined) {
						target[name] = copy;
					}
				}
			}
		}

		// Return the modified object
		return target;
	};
	//有一个返回值,包裹的插件对象
	
	jQuery.extend({noConflict : function(deep) {
					if (window.$ === jQuery) {
						window.$ = _$;
					}

					if (deep && window.jQuery === jQuery) {
						window.jQuery = _jQuery;
					}

					return jQuery;
				},

				// Is the DOM ready to be used? Set to true once it occurs.
				isReady : false,

				// A counter to track how many items to wait for before
				// the ready event fires. See #6781
				readyWait : 1,

				// Hold (or release) the ready event
				holdReady : function(hold) {
					if (hold) {
						jQuery.readyWait++;
					} else {
						jQuery.ready(true);
					}
				},

				// Handle when the DOM is ready
				ready : function(wait) {
					// Either a released hold or an DOMready/load event and
					// not yet ready
					if ((wait === true && !--jQuery.readyWait)
							|| (wait !== true && !jQuery.isReady)) {
						// Make sure body exists, at least, in case IE gets
						// a little overzealous (ticket #5443).
						if (!document.body) {
							return setTimeout(jQuery.ready, 1);
						}

						// Remember that the DOM is ready
						jQuery.isReady = true;

						// If a normal DOM Ready event fired, decrement, and
						// wait if need be
						if (wait !== true && --jQuery.readyWait > 0) {
							return;
						}

						// If there are functions bound, to execute
						readyList.fireWith(document, [ jQuery ]);

						// Trigger any bound ready events
						if (jQuery.fn.trigger) {
							jQuery(document).trigger("ready").off("ready");
						}
					}
				},

				bindReady : function() {
					if (readyList) {
						return;
					}

					readyList = jQuery.Callbacks("once memory");

					// Catch cases where $(document).ready() is called after
					// the
					// browser event has already occurred.
					if (document.readyState === "complete") {
						// Handle it asynchronously to allow scripts the
						// opportunity to delay ready
						return setTimeout(jQuery.ready, 1);
					}

					// Mozilla, Opera and webkit nightlies currently support
					// this event
					if (document.addEventListener) {
						// Use the handy event callback
						document.addEventListener("DOMContentLoaded",
								DOMContentLoaded, false);

						// A fallback to window.onload, that will always
						// work
						window.addEventListener("load", jQuery.ready, false);

						// If IE event model is used
					} else if (document.attachEvent) {
						// ensure firing before onload,
						// maybe late but safe also for iframes
						document.attachEvent("onreadystatechange",
								DOMContentLoaded);

						// A fallback to window.onload, that will always
						// work
						window.attachEvent("onload", jQuery.ready);

						// If IE and not a frame
						// continually check to see if the document is ready
						var toplevel = false;

						try {
							toplevel = window.frameElement == null;
						} catch (e) {
						}

						if (document.documentElement.doScroll && toplevel) {
							doScrollCheck();
						}
					}
				},

				// See test/unit/core.js for details concerning isFunction.
				// Since version 1.3, DOM methods and functions like alert
				// aren't supported. They return false on IE (#2968).
				isFunction : function(obj) {
					return jQuery.type(obj) === "function";
				},

				isArray : Array.isArray || function(obj) {
					return jQuery.type(obj) === "array";
				},

				isWindow : function(obj) {
					return obj != null && obj == obj.window;
				},

				isNumeric : function(obj) {
					return !isNaN(parseFloat(obj)) && isFinite(obj);
				},

				type : function(obj) {
					return obj == null ? String(obj) : class2type[toString
							.call(obj)]
							|| "object";
				},

				isPlainObject : function(obj) {
					// Must be an Object.
					// Because of IE, we also have to check the presence of
					// the constructor property.
					// Make sure that DOM nodes and window objects don't
					// pass through, as well
					if (!obj || jQuery.type(obj) !== "object" || obj.nodeType
							|| jQuery.isWindow(obj)) {
						return false;
					}

					try {
						// Not own constructor property must be Object
						if (obj.constructor
								&& !hasOwn.call(obj, "constructor")
								&& !hasOwn.call(obj.constructor.prototype,
										"isPrototypeOf")) {
							return false;
						}
					} catch (e) {
						// IE8,9 Will throw exceptions on certain host
						// objects #9897
						return false;
					}

					// Own properties are enumerated firstly, so to speed
					// up,
					// if last one is own, then all properties are own.

					var key;
					for (key in obj) {
					}

					return key === undefined || hasOwn.call(obj, key);
				},

				isEmptyObject : function(obj) {
					for ( var name in obj) {
						return false;
					}
					return true;
				},

				error : function(msg) {
					throw new Error(msg);
				},

				parseJSON : function(data) {
					if (typeof data !== "string" || !data) {
						return null;
					}

					// Make sure leading/trailing whitespace is removed (IE
					// can't handle it)
					data = jQuery.trim(data);

					// Attempt to parse using the native JSON parser first
					if (window.JSON && window.JSON.parse) {
						return window.JSON.parse(data);
					}

					// Make sure the incoming data is actual JSON
					// Logic borrowed from http://json.org/json2.js
					if (rvalidchars.test(data.replace(rvalidescape, "@")
							.replace(rvalidtokens, "]").replace(rvalidbraces,
									""))) {

						return (new Function("return " + data))();

					}
					jQuery.error("Invalid JSON: " + data);
				},

				// Cross-browser xml parsing
				parseXML : function(data) {
					if (typeof data !== "string" || !data) {
						return null;
					}
					var xml, tmp;
					try {
						if (window.DOMParser) { // Standard
							tmp = new DOMParser();
							xml = tmp.parseFromString(data, "text/xml");
						} else { // IE
							xml = new ActiveXObject("Microsoft.XMLDOM");
							xml.async = "false";
							xml.loadXML(data);
						}
					} catch (e) {
						xml = undefined;
					}
					if (!xml || !xml.documentElement
							|| xml.getElementsByTagName("parsererror").length) {
						jQuery.error("Invalid XML: " + data);
					}
					return xml;
				},

				noop : function() {
				},

				// Evaluates a script in a global context
				// Workarounds based on findings by Jim Driscoll
				// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
				globalEval : function(data) {
					if (data && rnotwhite.test(data)) {
						// We use execScript on Internet Explorer
						// We use an anonymous function so that context is
						// window
						// rather than jQuery in Firefox
						(window.execScript || function(data) {
							window["eval"].call(window, data);
						})(data);
					}
				},

				// Convert dashed to camelCase; used by the css and data
				// modules
				// Microsoft forgot to hump their vendor prefix (#9572)
				camelCase : function(string) {
					return string.replace(rmsPrefix, "ms-").replace(rdashAlpha,
							fcamelCase);
				},

				nodeName : function(elem, name) {
					return elem.nodeName
							&& elem.nodeName.toUpperCase() === name
									.toUpperCase();
				},

				// args is for internal usage only
				each : function(object, callback, args) {
					var name, i = 0, length = object.length, isObj = length === undefined
							|| jQuery.isFunction(object);

					if (args) {
						if (isObj) {
							for (name in object) {
								if (callback.apply(object[name], args) === false) {
									break;
								}
							}
						} else {
							for (; i < length;) {
								if (callback.apply(object[i++], args) === false) {
									break;
								}
							}
						}

						// A special, fast, case for the most common use of
						// each
					} else {
						if (isObj) {
							for (name in object) {
								if (callback.call(object[name], name,
										object[name]) === false) {
									break;
								}
							}
						} else {
							for (; i < length;) {
								if (callback.call(object[i], i, object[i++]) === false) {
									break;
								}
							}
						}
					}

					return object;
				},

				// Use native String.trim function wherever possible
				trim : trim ? function(text) {
					return text == null ? "" : trim.call(text);
				} :

				// Otherwise use our own trimming functionality
				function(text) {
					return text == null ? "" : text.toString().replace(
							trimLeft, "").replace(trimRight, "");
				},

				// results is for internal usage only
				makeArray : function(array, results) {
					var ret = results || [];

					if (array != null) {
						// The window, strings (and functions) also have
						// 'length'
						// Tweaked logic slightly to handle Blackberry 4.7
						// RegExp issues #6930

						if (array.length == null || type === "string"
								|| type === "function" || type === "regexp"
								|| jQuery.isWindow(array)) {
							push.call(ret, array);
						} else {
							jQuery.merge(ret, array);
						}
					}

					return ret;
				},

				inArray : function(elem, array, i) {
					var len;

					if (array) {
						if (indexOf) {
							return indexOf.call(array, elem, i);
						}

						len = array.length;
						i = i ? i < 0 ? Math.max(0, len + i) : i : 0;

						for (; i < len; i++) {
							// Skip accessing in sparse arrays
							if (i in array && array[i] === elem) {
								return i;
							}
						}
					}

					return -1;
				},

				merge : function(first, second) {
					var i = first.length, j = 0;

					if (typeof second.length === "number") {
						for (var l = second.length; j < l; j++) {
							first[i++] = second[j];
						}

					} else {
						while (second[j] !== undefined) {
							first[i++] = second[j++];
						}
					}

					first.length = i;

					return first;
				},

				grep : function(elems, callback, inv) {
					var ret = [], retVal;
					inv = !!inv;

					// Go through the array, only saving the items
					// that pass the validator function
					for (var i = 0, length = elems.length; i < length; i++) {
						retVal = !!callback(elems[i], i);
						if (inv !== retVal) {
							ret.push(elems[i]);
						}
					}

					return ret;
				},

				// arg is for internal usage only
				map : function(elems, callback, arg) {
					var value, key, ret = [], i = 0, length = elems.length,
					// jquery objects are treated as arrays
					isArray = elems instanceof jQuery
							|| length !== undefined
							&& typeof length === "number"
							&& ((length > 0 && elems[0] && elems[length - 1])
									|| length === 0 || jQuery.isArray(elems));

					// Go through the array, translating each of the items
					// to their
					if (isArray) {
						for (; i < length; i++) {
							value = callback(elems[i], i, arg);

							if (value != null) {
								ret[ret.length] = value;
							}
						}

						// Go through every key on the object,
					} else {
						for (key in elems) {
							value = callback(elems[key], key, arg);

							if (value != null) {
								ret[ret.length] = value;
							}
						}
					}

					// Flatten any nested arrays
					return ret.concat.apply([], ret);
				},

				// A global GUID counter for objects
				guid : 1,

				// Bind a function to a context, optionally partially
				// applying any
				// arguments.
				proxy : function(fn, context) {
					if (typeof context === "string") {
						var tmp = fn[context];
						context = fn;
						fn = tmp;
					}

					// Quick check to determine if target is callable, in
					// the spec
					// this throws a TypeError, but we will just return
					// undefined.
					if (!jQuery.isFunction(fn)) {
						return undefined;
					}

					// Simulated bind
					var args = slice.call(arguments, 2), proxy = function() {
						return fn.apply(context, args.concat(slice
								.call(arguments)));
					};

					// Set the guid of unique handler to the same of
					// original handler, so it can be removed
					proxy.guid = fn.guid = fn.guid || proxy.guid
							|| jQuery.guid++;

					return proxy;
				},

				// Mutifunctional method to get and set values to a
				// collection
				// The value/s can optionally be executed if it's a function
				access : function(elems, fn, key, value, chainable, emptyGet,
						pass) {
					var exec, bulk = key == null, i = 0, length = elems.length;

					// Sets many values
					if (key && typeof key === "object") {
						for (i in key) {
							jQuery.access(elems, fn, i, key[i], 1, emptyGet,
									value);
						}
						chainable = 1;

						// Sets one value
					} else if (value !== undefined) {
						// Optionally, function values get executed if exec
						// is true
						exec = pass === undefined && jQuery.isFunction(value);

						if (bulk) {
							// Bulk operations only iterate when executing
							// function values
							if (exec) {
								exec = fn;
								fn = function(elem, key, value) {
									return exec.call(jQuery(elem), value);
								};

								// Otherwise they run against the entire set
							} else {
								fn.call(elems, value);
								fn = null;
							}
						}

						if (fn) {
							for (; i < length; i++) {
								fn(elems[i], key, exec ? value.call(elems[i],
										i, fn(elems[i], key)) : value, pass);
							}
						}

						chainable = 1;
					}

					return chainable ? elems :

					// Gets
					bulk ? fn.call(elems) : length ? fn(elems[0], key)
							: emptyGet;
				},

				now : function() {
					return (new Date()).getTime();
				},

				// Use of jQuery.browser is frowned upon.
				// More details:
				// http://docs.jquery.com/Utilities/jQuery.browser
				uaMatch : function(ua) {
					ua = ua.toLowerCase();

					var match = rwebkit.exec(ua) || ropera.exec(ua)
							|| rmsie.exec(ua) || ua.indexOf("compatible") < 0
							&& rmozilla.exec(ua) || [];

					return {
						browser : match[1] || "",
						version : match[2] || "0"
					};
				},

				sub : function() {
					function jQuerySub(selector, context) {
						return new jQuerySub.fn.init(selector, context);
					}
					jQuery.extend(true, jQuerySub, this);
					jQuerySub.superclass = this;
					jQuerySub.fn = jQuerySub.prototype = this();
					jQuerySub.fn.constructor = jQuerySub;
					jQuerySub.sub = this.sub;
					jQuerySub.fn.init = function init(selector, context) {
						if (context && context instanceof jQuery
								&& !(context instanceof jQuerySub)) {
							context = jQuerySub(context);
						}

						return jQuery.fn.init.call(this, selector, context,
								rootjQuerySub);
					};
					jQuerySub.fn.init.prototype = jQuerySub.fn;
					var rootjQuerySub = jQuerySub(document);
					return jQuerySub;
				},

				browser : {}
			});

	// Populate the class2type map
	jQuery.each("Boolean Number String Function Array Date RegExp Object"
			.split(" "), function(i, name) {
		class2type["[object " + name + "]"] = name.toLowerCase();
	});

	browserMatch = jQuery.uaMatch(userAgent);
	if (browserMatch.browser) {
		jQuery.browser[browserMatch.browser] = true;
		jQuery.browser.version = browserMatch.version;
	}

	// Deprecated, use jQuery.browser.webkit instead
	if (jQuery.browser.webkit) {
		jQuery.browser.safari = true;
	}

	// IE doesn't match non-breaking spaces with \s
	if (rnotwhite.test("\xA0")) {
		trimLeft = /^[\s\xA0]+/;
		trimRight = /[\s\xA0]+$/;
	}

	// All jQuery objects should point back to these
	rootjQuery = jQuery(document);

	// Cleanup functions for the document ready method
	if (document.addEventListener) {
		DOMContentLoaded = function() {
			document.removeEventListener("DOMContentLoaded", DOMContentLoaded,
					false);
			jQuery.ready();
		};

	} else if (document.attachEvent) {
		DOMContentLoaded = function() {
			// Make sure body exists, at least, in case IE gets a little
			// overzealous (ticket #5443).
			if (document.readyState === "complete") {
				document.detachEvent("onreadystatechange", DOMContentLoaded);
				jQuery.ready();
			}
		};
	}

	// The DOM ready check for Internet Explorer
	function doScrollCheck() {
		if (jQuery.isReady) {
			return;
		}

		try {
			// If IE is used, use the trick by Diego Perini
			// http://javascript.nwbox.com/IEContentLoaded/
			document.documentElement.doScroll("left");
		} catch (e) {
			setTimeout(doScrollCheck, 1);
			return;
		}

		// and execute any waiting functions
		jQuery.ready();
	}

	return jQuery;

})();

抱歉!评论已关闭.