Jump To …

01-core.js

jQuery Annotated Source. You can view the source and contribute on Github.

Home | Next Chapter

jQuery JavaScript Library v1.6.2
http://jquery.com
Copyright 2011, John Resig
Dual licensed under the MIT or GPL Version 2 licenses.
http://jquery.org/license
Includes Sizzle.js
http://sizzlejs.com
Copyright 2011, The Dojo Foundation
Released under the MIT, BSD, and GPL Licenses.
Date: Thu Jun 30 14:16:56 2011 -0400

Chapter 1: Core

(function( window, undefined ) {

Use the correct document accordingly with window argument (sandbox)

var document = window.document,
  navigator = window.navigator,
  location = window.location;

Hello, jQuery

var jQuery = (function() {

Define a local copy of jQuery. The jQuery object is actually just the init constructor 'enhanced'

  var jQuery = function( selector, context ) {
    return new jQuery.fn.init( selector, context, rootjQuery );
  },

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 (both of which we optimize for)

  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+$/,

Check for digits

  rdigit = /\d/,

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])/ig,

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 prototype

jQuery.fn = jQuery.prototype = {
  
  constructor: jQuery,
  

Main jQuery function

  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.6.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;
  },
  

Retrieve all the DOM elements contained in the jQuery set, as an array

  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 );
  },
  

Specify a function to execute when the DOM is fully loaded.

  ready: function( fn ) {

Attach the listeners

    jQuery.bindReady();

Add the callback

    readyList.done( fn );

    return this;
  },
  

Reduce the set of matched elements to the one at the specified index

  eq: function( i ) {
    return i === -1 ?
      this.slice( i ) :
      this.slice( i, +i + 1 );
  },
  

Reduce the set of matched elements to the first in the set

  first: function() {
    return this.eq( 0 );
  },
  

Reduce the set of matched elements to the final one in the set

  last: function() {
    return this.eq( -1 );
  },
  

Reduce the set of matched elements to a subset specified by a range of indices

  slice: function() {
    return this.pushStack( slice.apply( this, arguments ),
      "slice", slice.call(arguments).join(",") );
  },
  

Pass each element in the current matched set through a function, producing a new jQuery object containing the return values

  map: function( callback ) {
    return this.pushStack( jQuery.map(this, function( elem, i ) {
      return callback.call( elem, i, elem );
    }));
  },
  

End the most recent filtering operation in the current chain and return the set of matched elements to its previous state

  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
};

Give the init function the jQuery prototype for later instantiation

jQuery.fn.init.prototype = jQuery.fn;

Utilities

Merge the contents of two or more objects together into the first object

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({

Relinquish jQuery's control of the $ variable

  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.resolveWith( document, [ jQuery ] );

Trigger any bound ready events

      if ( jQuery.fn.trigger ) {
        jQuery( document ).trigger( "ready" ).unbind( "ready" );
      }
    }
  },

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

    readyList = jQuery._Deferred();

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";
  },
  

Determine whether the argument is an array

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

A crude way of determining if an object is a window

  isWindow: function( obj ) {
    return obj && typeof obj === "object" && "setInterval" in obj;
  },

  isNaN: function( obj ) {
    return obj == null || !rdigit.test( obj ) || isNaN( obj );
  },
  

Determine the internal JavaScript [[Class]] of an object

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

Check to see if an object is a plain object (created using "{}" or "new 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;
    }

Not own constructor property must be Object

    if ( obj.constructor &&
      !hasOwn.call(obj, "constructor") &&
      !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
      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 );
  },

Check to see if an object is empty (contains no properties).

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

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

Takes a well-formed JSON string and returns the resulting JavaScript object.

  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 (xml & tmp used internally)

  parseXML: function( data , xml , tmp ) {

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

    tmp = xml.documentElement;

    if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
      jQuery.error( "Invalid XML: " + data );
    }

    return xml;
  },

An empty function

  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 );
    }
  },

Converts a dashed string to camelCased string; Used by both the css and data modules

  camelCase: function( string ) {
    return string.replace( rdashAlpha, fcamelCase );
  },

Returns the uppercase node name

  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' The extra typeof function check is to prevent crashes in Safari 2 (See: #3039) Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930

      var type = jQuery.type( array );

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

    return ret;
  },

Search for a specified value within an array and return its index (or -1 if not found).

  inArray: function( elem, array ) {

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

    for ( var i = 0, length = array.length; i < length; i++ ) {
      if ( array[ i ] === elem ) {
        return i;
      }
    }

    return -1;
  },
  

Merge the contents of two arrays together into the first array.

  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;
  },

Finds the elements of an array which satisfy a filter function. The original array is not affected

  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;
  },

Translate all items in an array or object to new array of items.

  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, key, value, exec, fn, pass ) {
    var length = elems.length;

Setting many attributes

    if ( typeof key === "object" ) {
      for ( var k in key ) {
        jQuery.access( elems, k, key[k], exec, fn, value );
      }
      return elems;
    }

Setting one attribute

    if ( value !== undefined ) {

Optionally, function values get executed if exec is true

      exec = !pass && exec && jQuery.isFunction(value);

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

      return elems;
    }

Getting an attribute

    return length ? fn( elems[0], key ) : undefined;
  },
  

Return a number representing the current time

  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" };
  },

Creates a new copy of jQuery whose properties and methods can be modified without affecting the original jQuery object.

  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();
});

Pass user agent to internal uaMatch() function

browserMatch = jQuery.uaMatch( userAgent );

Set properties for jQuery.browser

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;
  }

If IE is used, use the trick by Diego Perini http://javascript.nwbox.com/IEContentLoaded/

  try {
    document.documentElement.doScroll("left");
  } catch(e) {
    setTimeout( doScrollCheck, 1 );
    return;
  }

and execute any waiting functions

  jQuery.ready();
}

return jQuery;

})();