Fixed bug with jQuery: height computation for hidden elements
[jquery.git] / src / jquery / jquery.js
index 470dbde..9daa400 100644 (file)
@@ -2,8 +2,8 @@
  * jQuery - New Wave Javascript
  *
  * Copyright (c) 2006 John Resig (jquery.com)
- * Licensed under the MIT License:
- *   http://www.opensource.org/licenses/mit-license.php
+ * Dual licensed under the MIT (MIT-LICENSE.txt) 
+ * and GPL (GPL-LICENSE.txt) licenses.
  *
  * $Date$
  * $Rev$
@@ -26,45 +26,24 @@ window.undefined = window.undefined;
  * @constructor
  * @private
  * @name jQuery
+ * @cat Core
  */
 function jQuery(a,c) {
 
-       // Initalize the extra macro functions
-       if ( !jQuery.initDone ) jQuery.init();
-
        // Shortcut for document ready (because $(document).each() is silly)
        if ( a && a.constructor == Function && jQuery.fn.ready )
                return jQuery(document).ready(a);
 
-       // Make sure t hat a selection was provided
+       // Make sure that a selection was provided
        a = a || jQuery.context || document;
 
-       /*
-        * Handle support for overriding other $() functions. Way too many libraries
-        * provide this function to simply ignore it and overwrite it.
-        */
-       /*
-       // Check to see if this is a possible collision case
-       if ( jQuery._$ && !c && a.constructor == String && 
-      
-               // Make sure that the expression is a colliding one
-               !/[^a-zA-Z0-9_-]/.test(a) &&
-        
-               // and that there are no elements that match it
-               // (this is the one truly ambiguous case)
-               !document.getElementsByTagName(a).length )
-
-                       // Use the default method, in case it works some voodoo
-                       return jQuery._$( a );
-       */
-
        // Watch for when a jQuery object is passed as the selector
        if ( a.jquery )
-               return a;
+               return jQuery( jQuery.merge( a, [] ) );
 
        // Watch for when a jQuery object is passed at the context
        if ( c && c.jquery )
-               return jQuery(c.get()).find(a);
+               return jQuery( c ).find(a);
        
        // If the context is global, return a new object
        if ( window == this )
@@ -82,14 +61,119 @@ function jQuery(a,c) {
                // Find the matching elements and save them for later
                jQuery.find( a, c ) );
 
+  // See if an extra function was provided
        var fn = arguments[ arguments.length - 1 ];
+       
+       // If so, execute it in context
        if ( fn && fn.constructor == Function )
                this.each(fn);
 }
 
 // Map over the $ in case of overwrite
-if ( $ )
+if ( typeof $ != "undefined" )
        jQuery._$ = $;
+       
+/**
+ * This function accepts a string containing a CSS selector, 
+ * basic XPath, or raw HTML, which is then used to match a set of elements.
+ * The HTML string is different from the traditional selectors in that
+ * it creates the DOM elements representing that HTML string, on the fly,
+ * to be (assumedly) inserted into the document later.
+ *
+ * The core functionality of jQuery centers around this function. 
+ * Everything in jQuery is based upon this, or uses this in some way. 
+ * The most basic use of this function is to pass in an expression 
+ * (usually consisting of CSS or XPath), which then finds all matching 
+ * elements and remembers them for later use.
+ *
+ * By default, $() looks for DOM elements within the context of the 
+ * current HTML document.
+ *
+ * @example $("div > p")
+ * @desc This finds all p elements that are children of a div element.
+ * @before <p>one</p> <div><p>two</p></div> <p>three</p>
+ * @result [ <p>two</p> ]
+ *
+ * @example $("<div><p>Hello</p></div>").appendTo("#body")
+ * @desc Creates a div element (and all of its contents) dynamically, and appends it to the element with the ID of body.
+ *
+ * @name $
+ * @param String expr An expression to search with, or a string of HTML to create on the fly.
+ * @cat Core
+ * @type jQuery
+ */
+/**
+ * This function accepts a string containing a CSS selector, or
+ * basic XPath, which is then used to match a set of elements with the
+ * context of the specified DOM element, or document
+ *
+ * @example $("div", xml.responseXML)
+ * @desc This finds all div elements within the specified XML document.
+ *
+ * @name $
+ * @param String expr An expression to search with.
+ * @param Element context A DOM Element, or Document, representing the base context.
+ * @cat Core
+ * @type jQuery
+ */
+/**
+ * Wrap jQuery functionality around a specific DOM Element.
+ * This function also accepts XML Documents and Window objects
+ * as valid arguments (even though they are not DOM Elements).
+ *
+ * @example $(document).find("div > p")
+ * @before <p>one</p> <div><p>two</p></div> <p>three</p>
+ * @result [ <p>two</p> ]
+ *
+ * @example $(document).ready( loaded );
+ * @desc Executes the "loaded" function when the DOM is ready to
+ * be manipulated.
+ *
+ * @name $
+ * @param Element elem A DOM element to be encapsulated by a jQuery object.
+ * @cat Core
+ * @type jQuery
+ */
+/**
+ * Wrap jQuery functionality around a set of DOM Elements.
+ *
+ * @example $( myForm.elements ).hide()
+ * @desc Hides all the input elements within a form
+ *
+ * @name $
+ * @param Array<Element> elems An array of DOM elements to be encapsulated by a jQuery object.
+ * @cat Core
+ * @type jQuery
+ */
+/**
+ * A shorthand for $(document).ready(), allowing you to bind a function
+ * to be executed when the DOM document has finished loading.
+ *
+ * @example $( loaded )
+ * @desc Executes the function "loaded" when the DOM is ready to be used.
+ *
+ * @name $
+ * @param Function fn The function to execute when the DOM is ready.
+ * @cat Core
+ * @type jQuery
+ */
+/**
+ * A means of creating a duplicate copy of a jQuery object.
+ *
+ * @example var div = $("div");
+ * $( div ).find("p")
+ * @desc Locates all p elements with all div elements, without disrupting the original jQuery object contained in 'div'.
+ *
+ * @name $
+ * @param jQuery obj The jQuery object to be cloned.
+ * @cat Core
+ * @type jQuery
+ */
 
 // Map the jQuery namespace to the '$' one
 var $ = jQuery;
@@ -212,7 +296,15 @@ jQuery.fn = jQuery.prototype = {
         * argument representing the position of the element in the matched
         * set.
         *
-        * @example $("img").each(function(){ this.src = "test.jpg"; });
+        * @example $("img").each(function(){
+        *   this.src = "test.jpg";
+        * });
+        * @before <img/> <img/>
+        * @result <img src="test.jpg"/> <img src="test.jpg"/>
+        *
+        * @example $("img").each(function(i){
+        *   alert( "Image #" + i + " is " + this );
+        * });
         * @before <img/> <img/>
         * @result <img src="test.jpg"/> <img src="test.jpg"/>
         *
@@ -232,6 +324,14 @@ jQuery.fn = jQuery.prototype = {
        each: function( fn, args ) {
                return jQuery.each( this, fn, args );
        },
+
+       index: function( obj ) {
+               var pos = -1;
+               this.each(function(i){
+                       if ( this == obj ) pos = i;
+               });
+               return pos;
+       },
        
        /**
         * Access a property on the first matched element.
@@ -257,12 +357,10 @@ jQuery.fn = jQuery.prototype = {
         * @before <img/>
         * @result <img src="test.jpg" alt="Test Image"/>
         *
-        * @test var div = $("div");
-        * div.attr({foo: 'baz', zoo: 'ping'});
-        * var pass = true;
-        * for ( var i = 0; i < div.size(); i++ ) {
-        *   if ( div.get(i).foo != "baz" && div.get(i).zoo != "ping" ) pass = false;
-        * }
+        * @test var pass = true;
+        * $("div").attr({foo: 'baz', zoo: 'ping'}).each(function(){
+        *   if ( this.getAttribute('foo') != "baz" && this.getAttribute('zoo') != "ping" ) pass = false;
+        * });
         * ok( pass, "Set Multiple Attributes" );
         *
         * @name attr
@@ -282,7 +380,7 @@ jQuery.fn = jQuery.prototype = {
         * div.attr("foo", "bar");
         * var pass = true;
         * for ( var i = 0; i < div.size(); i++ ) {
-        *   if ( div.get(i).foo != "bar" ) pass = false;
+        *   if ( div.get(i).getAttribute('foo') != "bar" ) pass = false;
         * }
         * ok( pass, "Set Attribute" );
         *
@@ -316,7 +414,7 @@ jQuery.fn = jQuery.prototype = {
                        // Look for the case where we're accessing a style value
                        jQuery[ type || "attr" ]( this[0], key );
        },
-       
+
        /**
         * Access a style property on the first matched element.
         * This method makes it easy to retreive a style property value
@@ -383,8 +481,9 @@ jQuery.fn = jQuery.prototype = {
                for ( var j = 0; j < e.length; j++ ) {
                        var r = e[j].childNodes;
                        for ( var i = 0; i < r.length; i++ )
-                               t += r[i].nodeType != 1 ?
-                                       r[i].nodeValue : jQuery.fn.text([ r[i] ]);
+                               if ( r[i].nodeType != 8 )
+                                       t += r[i].nodeType != 1 ?
+                                               r[i].nodeValue : jQuery.fn.text([ r[i] ]);
                }
                return t;
        },
@@ -395,9 +494,30 @@ jQuery.fn = jQuery.prototype = {
         * stucture into a document, without ruining the original semantic
         * qualities of a document.
         *
-        * The way that is works is that it goes through the first element argument
-        * provided and finds the deepest element within the structure - it is that
-        * element that will en-wrap everything else.
+        * This works by going through the first element 
+        * provided (which is generated, on the fly, from the provided HTML)
+        * and finds the deepest ancestor element within its 
+        * structure - it is that element that will en-wrap everything else.
+        *
+        * @example $("p").wrap("<div class='wrap'></div>");
+        * @before <p>Test Paragraph.</p>
+        * @result <div class='wrap'><p>Test Paragraph.</p></div>
+        *
+        * @name wrap
+        * @type jQuery
+        * @param String html A string of HTML, that will be created on the fly and wrapped around the target.
+        * @cat DOM/Manipulation
+        */
+        
+       /**
+        * Wrap all matched elements with a structure of other elements.
+        * This wrapping process is most useful for injecting additional
+        * stucture into a document, without ruining the original semantic
+        * qualities of a document.
+        *
+        * This works by going through the first element 
+        * provided and finding the deepest ancestor element within its 
+        * structure - it is that element that will en-wrap everything else.
         *
         * @example $("p").wrap("<div class='wrap'></div>");
         * @before <p>Test Paragraph.</p>
@@ -405,10 +525,7 @@ jQuery.fn = jQuery.prototype = {
         *
         * @name wrap
         * @type jQuery
-        * @any String html A string of HTML, that will be created on the fly and wrapped around the target.
-        * @any Element elem A DOM element that will be wrapped.
-        * @any Array<Element> elems An array of elements, the first of which will be wrapped.
-        * @any Object obj Any object, converted to a string, then a text node.
+        * @param Element elem A DOM element that will be wrapped.
         * @cat DOM/Manipulation
         */
        wrap: function() {
@@ -433,7 +550,8 @@ jQuery.fn = jQuery.prototype = {
        },
        
        /**
-        * Append any number of elements to the inside of all matched elements.
+        * Append any number of elements to the inside of every matched elements,
+        * generated from the provided HTML.
         * This operation is similar to doing an appendChild to all the 
         * specified elements, adding them into the document.
         * 
@@ -443,10 +561,37 @@ jQuery.fn = jQuery.prototype = {
         *
         * @name append
         * @type jQuery
-        * @any String html A string of HTML, that will be created on the fly and appended to the target.
-        * @any Element elem A DOM element that will be appended.
-        * @any Array<Element> elems An array of elements, all of which will be appended.
-        * @any Object obj Any object, converted to a string, then a text node.
+        * @param String html A string of HTML, that will be created on the fly and appended to the target.
+        * @cat DOM/Manipulation
+        */
+        
+       /**
+        * Append an element to the inside of all matched elements.
+        * This operation is similar to doing an appendChild to all the 
+        * specified elements, adding them into the document.
+        * 
+        * @example $("p").append( $("#foo")[0] );
+        * @before <p>I would like to say: </p><b id="foo">Hello</b>
+        * @result <p>I would like to say: <b id="foo">Hello</b></p>
+        *
+        * @name append
+        * @type jQuery
+        * @param Element elem A DOM element that will be appended.
+        * @cat DOM/Manipulation
+        */
+        
+       /**
+        * Append any number of elements to the inside of all matched elements.
+        * This operation is similar to doing an appendChild to all the 
+        * specified elements, adding them into the document.
+        * 
+        * @example $("p").append( $("b") );
+        * @before <p>I would like to say: </p><b>Hello</b>
+        * @result <p>I would like to say: <b>Hello</b></p>
+        *
+        * @name append
+        * @type jQuery
+        * @param Array<Element> elems An array of elements, all of which will be appended.
         * @cat DOM/Manipulation
         */
        append: function() {
@@ -456,20 +601,48 @@ jQuery.fn = jQuery.prototype = {
        },
        
        /**
-        * Prepend any number of elements to the inside of all matched elements.
+        * Prepend any number of elements to the inside of every matched elements,
+        * generated from the provided HTML.
+        * This operation is the best way to insert dynamically created elements 
+        * inside, at the beginning, of all the matched element.
+        * 
+        * @example $("p").prepend("<b>Hello</b>");
+        * @before <p>I would like to say: </p>
+        * @result <p><b>Hello</b>I would like to say: </p>
+        *
+        * @name prepend
+        * @type jQuery
+        * @param String html A string of HTML, that will be created on the fly and appended to the target.
+        * @cat DOM/Manipulation
+        */
+        
+       /**
+        * Append an element to the inside of all matched elements.
+        * This operation is the best way to insert an element inside, at the 
+        * beginning, of all the matched element.
+        * 
+        * @example $("p").prepend( $("#foo")[0] );
+        * @before <p>I would like to say: </p><b id="foo">Hello</b>
+        * @result <p><b id="foo">Hello</b>I would like to say: </p>
+        *
+        * @name prepend
+        * @type jQuery
+        * @param Element elem A DOM element that will be appended.
+        * @cat DOM/Manipulation
+        */
+        
+       /**
+        * Append any number of elements to the inside of all matched elements.
         * This operation is the best way to insert a set of elements inside, at the 
         * beginning, of all the matched element.
         * 
-        * @example $("p").prepend("<b>Hello</b>");
-        * @before <p>, how are you?</p>
-        * @result <p><b>Hello</b>, how are you?</p>
+        * @example $("p").prepend( $("b") );
+        * @before <p>I would like to say: </p><b>Hello</b>
+        * @result <p><b>Hello</b>I would like to say: </p>
         *
         * @name prepend
         * @type jQuery
-        * @any String html A string of HTML, that will be created on the fly and prepended to the target.
-        * @any Element elem A DOM element that will be prepended.
-        * @any Array<Element> elems An array of elements, all of which will be prepended.
-        * @any Object obj Any object, converted to a string, then a text node.
+        * @param Array<Element> elems An array of elements, all of which will be appended.
         * @cat DOM/Manipulation
         */
        prepend: function() {
@@ -479,18 +652,42 @@ jQuery.fn = jQuery.prototype = {
        },
        
        /**
-        * Insert any number of elements before each of the matched elements.
+        * Insert any number of dynamically generated elements before each of the 
+        * matched elements.
         * 
         * @example $("p").before("<b>Hello</b>");
-        * @before <p>how are you?</p>
-        * @result <b>Hello</b><p>how are you?</p>
+        * @before <p>I would like to say: </p>
+        * @result <b>Hello</b><p>I would like to say: </p>
+        *
+        * @name before
+        * @type jQuery
+        * @param String html A string of HTML, that will be created on the fly and appended to the target.
+        * @cat DOM/Manipulation
+        */
+        
+       /**
+        * Insert an element before each of the matched elements.
+        * 
+        * @example $("p").before( $("#foo")[0] );
+        * @before <p>I would like to say: </p><b id="foo">Hello</b>
+        * @result <b id="foo">Hello</b><p>I would like to say: </p>
+        *
+        * @name before
+        * @type jQuery
+        * @param Element elem A DOM element that will be appended.
+        * @cat DOM/Manipulation
+        */
+        
+       /**
+        * Insert any number of elements before each of the matched elements.
+        * 
+        * @example $("p").before( $("b") );
+        * @before <p>I would like to say: </p><b>Hello</b>
+        * @result <b>Hello</b><p>I would like to say: </p>
         *
         * @name before
         * @type jQuery
-        * @any String html A string of HTML, that will be created on the fly and inserted.
-        * @any Element elem A DOM element that will beinserted.
-        * @any Array<Element> elems An array of elements, all of which will be inserted.
-        * @any Object obj Any object, converted to a string, then a text node.
+        * @param Array<Element> elems An array of elements, all of which will be appended.
         * @cat DOM/Manipulation
         */
        before: function() {
@@ -500,18 +697,42 @@ jQuery.fn = jQuery.prototype = {
        },
        
        /**
+        * Insert any number of dynamically generated elements after each of the 
+        * matched elements.
+        * 
+        * @example $("p").after("<b>Hello</b>");
+        * @before <p>I would like to say: </p>
+        * @result <p>I would like to say: </p><b>Hello</b>
+        *
+        * @name after
+        * @type jQuery
+        * @param String html A string of HTML, that will be created on the fly and appended to the target.
+        * @cat DOM/Manipulation
+        */
+        
+       /**
+        * Insert an element after each of the matched elements.
+        * 
+        * @example $("p").after( $("#foo")[0] );
+        * @before <b id="foo">Hello</b><p>I would like to say: </p>
+        * @result <p>I would like to say: </p><b id="foo">Hello</b>
+        *
+        * @name after
+        * @type jQuery
+        * @param Element elem A DOM element that will be appended.
+        * @cat DOM/Manipulation
+        */
+        
+       /**
         * Insert any number of elements after each of the matched elements.
         * 
-        * @example $("p").after("<p>I'm doing fine.</p>");
-        * @before <p>How are you?</p>
-        * @result <p>How are you?</p><p>I'm doing fine.</p>
+        * @example $("p").after( $("b") );
+        * @before <b>Hello</b><p>I would like to say: </p>
+        * @result <p>I would like to say: </p><b>Hello</b>
         *
         * @name after
         * @type jQuery
-        * @any String html A string of HTML, that will be created on the fly and inserted.
-        * @any Element elem A DOM element that will beinserted.
-        * @any Array<Element> elems An array of elements, all of which will be inserted.
-        * @any Object obj Any object, converted to a string, then a text node.
+        * @param Array<Element> elems An array of elements, all of which will be appended.
         * @cat DOM/Manipulation
         */
        after: function() {
@@ -559,6 +780,27 @@ jQuery.fn = jQuery.prototype = {
                        return jQuery.find(t,a);
                }), arguments );
        },
+
+       /**
+        * Create cloned copies of all matched DOM Elements. This does
+        * not create a cloned copy of this particular jQuery object,
+        * instead it creates duplicate copies of all DOM Elements.
+        * This is useful for moving copies of the elements to another
+        * location in the DOM.
+        *
+        * @example $("b").clone().prependTo("p");
+        * @before <b>Hello</b><p>, how are you?</p>
+        * @result <b>Hello</b><p><b>Hello</b>, how are you?</p>
+        *
+        * @name clone
+        * @type jQuery
+        * @cat DOM/Manipulation
+        */
+       clone: function(deep) {
+               return this.pushStack( jQuery.map( this, function(a){
+                       return a.cloneNode( deep != undefined ? deep : true );
+               }), arguments );
+       },
        
        /**
         * Removes all elements from the set of matched elements that do not 
@@ -636,6 +878,7 @@ jQuery.fn = jQuery.prototype = {
         * @example $("p").not("#selected")
         * @before <p>Hello</p><p id="selected">Hello Again</p>
         * @result [ <p>Hello</p> ]
+        * @test cmpOK($("#main > p#ap > a").not("#google").length, "==", 2, ".not")
         *
         * @name not
         * @type jQuery
@@ -673,7 +916,7 @@ jQuery.fn = jQuery.prototype = {
         * @name add
         * @type jQuery
         * @param Array<Element> els An array of Elements to add
-        * @cat jQuery
+        * @cat DOM/Traversing
         */
 
        /**
@@ -687,7 +930,7 @@ jQuery.fn = jQuery.prototype = {
         * @name add
         * @type jQuery
         * @param Element el An Element to add
-        * @cat jQuery
+        * @cat DOM/Traversing
         */
        add: function(t) {
                return this.pushStack( jQuery.merge( this, t.constructor == String ?
@@ -702,7 +945,7 @@ jQuery.fn = jQuery.prototype = {
         * @member jQuery
         * @param {String} expr The expression with which to filter
         * @type Boolean
-        * @cat jQuery
+        * @cat DOM/Traversing
         */
        is: function(expr) {
                return expr ? jQuery.filter(expr,this).r.length > 0 : this.length > 0;
@@ -718,6 +961,7 @@ jQuery.fn = jQuery.prototype = {
         * @param Number int
         * @param Function fn The function doing the DOM manipulation.
         * @type jQuery
+        * @cat Core
         */
        domManip: function(args, table, dir, fn){
                var clone = this.size() > 1;
@@ -751,6 +995,7 @@ jQuery.fn = jQuery.prototype = {
         * @param Array a
         * @param Array args
         * @type jQuery
+        * @cat Core
         */
        pushStack: function(a,args) {
                var fn = args && args[args.length-1];
@@ -763,7 +1008,7 @@ jQuery.fn = jQuery.prototype = {
                        var old = this.get();
                        this.get( a );
                        if ( fn.constructor == Function )
-                               return this.each( fn );
+                               this.each( fn );
                        this.get( old );
                }
 
@@ -777,15 +1022,15 @@ jQuery.fn = jQuery.prototype = {
  * @private
  * @name extend
  * @param Object obj
- * @param Object prop
  * @type Object
+ * @cat Core
  */
  
 /**
  * Extend one object with another, returning the original,
  * modified, object. This is a great utility for simple inheritance.
  *
- * @name jQuery.extend
+ * @name $.extend
  * @param Object obj The object to extend
  * @param Object prop The object that will be merged into the first.
  * @type Object
@@ -799,11 +1044,10 @@ jQuery.extend = jQuery.fn.extend = function(obj,prop) {
 
 jQuery.extend({
        /**
-        * 
-        *
         * @private
         * @name init
         * @type undefined
+        * @cat Core
         */
        init: function(){
                jQuery.initDone = true;
@@ -822,7 +1066,7 @@ jQuery.extend({
                                var a = arguments;
                                return this.each(function(){
                                        for ( var j = 0; j < a.length; j++ )
-                                               $(a[j])[n]( this );
+                                               jQuery(a[j])[n]( this );
                                });
                        };
                });
@@ -849,7 +1093,7 @@ jQuery.extend({
                });
        
                jQuery.each( jQuery.macros.css, function(i,n){
-                       jQuery.fn[ i ] = function(h) {
+                       jQuery.fn[ n ] = function(h) {
                                return h == undefined ?
                                        ( this.length ? jQuery.css( this[0], n ) : null ) :
                                        this.css( n, h );
@@ -862,7 +1106,7 @@ jQuery.extend({
         * A generic iterator function, which can be used to seemlessly
         * iterate over both objects and arrays.
         *
-        * @name jQuery.each
+        * @name $.each
         * @param Object obj The object, or array, to iterate over.
         * @param Object fn The function that will be executed on every object.
         * @type Object
@@ -889,7 +1133,7 @@ jQuery.extend({
                                        new RegExp("(^|\\s*\\b[^-])"+c+"($|\\b(?=[^-]))", "g"), "");
                },
                has: function(e,a) {
-                       if ( e.className )
+                       if ( e.className != undefined )
                                e = e.className;
                        return new RegExp("(^|\\s)" + a + "(\\s|$)").test(e);
                }
@@ -922,36 +1166,61 @@ jQuery.extend({
                                if (jQuery.css(e,"display") != "none") {
                                        oHeight = e.offsetHeight;
                                        oWidth = e.offsetWidth;
-                               } else
-                                       jQuery.swap( e, { visibility: "hidden", position: "absolute", display: "" },
-                                               function(){
-                                                       oHeight = e.clientHeight;
-                                                       oWidth = e.clientWidth;
-                                               });
+                               } else {
+                                       e = jQuery(e.cloneNode(true)).css({
+                                               visibility: "hidden", position: "absolute", display: "block", right: "0", left: "0"
+                                       }).appendTo(e.parentNode)[0];
+
+                                       var parPos = jQuery.css(e.parentNode,"position");
+                                       if ( parPos == "" || parPos == "static" )
+                                               e.parentNode.style.position = "relative";
+
+                                       oHeight = e.clientHeight;
+                                       oWidth = e.clientWidth;
+                                       
+                                       if ( parPos == "" || parPos == "static" )
+                                               e.parentNode.style.position = "static";
+
+                                       e.parentNode.removeChild(e);
+                               }
                        });
        
                        return p == "height" ? oHeight : oWidth;
                } else if ( p == "opacity" && jQuery.browser.msie )
-                       return parseFloat(  jQuery.curCSS(e,"filter").replace(/[^0-9.]/,"") ) || 1;
+                       return parseFloat( jQuery.curCSS(e,"filter").replace(/[^0-9.]/,"") ) || 1;
 
                return jQuery.curCSS( e, p );
        },
 
-       curCSS: function(e,p,force) {
-               var r;
+       curCSS: function(elem, prop, force) {
+               var ret;
        
-               if (!force && e.style[p])
-                       r = e.style[p];
-               else if (e.currentStyle) {
-                       p = p.replace(/\-(\w)/g,function(m,c){return c.toUpperCase()}); 
-                       r = e.currentStyle[p];
+               if (!force && elem.style[prop]) {
+
+                       ret = elem.style[prop];
+
+               } else if (elem.currentStyle) {
+
+                       var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase()}); 
+                       ret = elem.currentStyle[prop] || elem.currentStyle[newProp];
+
                } else if (document.defaultView && document.defaultView.getComputedStyle) {
-                       p = p.replace(/([A-Z])/g,"-$1").toLowerCase();
-                       var s = document.defaultView.getComputedStyle(e,"");
-                       r = s ? s.getPropertyValue(p) : null;
+
+                       prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase();
+                       var cur = document.defaultView.getComputedStyle(elem, null);
+
+                       if ( cur )
+                               ret = cur.getPropertyValue(prop);
+                       else if ( prop == 'display' )
+                               ret = 'none';
+                       else
+                               jQuery.swap(elem, { display: 'block' }, function() {
+                                       ret = document.defaultView.getComputedStyle(this,null).getPropertyValue(prop);
+                               });
+
                }
                
-               return r;
+               return ret;
        },
        
        clean: function(a) {
@@ -1007,6 +1276,7 @@ jQuery.extend({
                        odd: "i%2",
                        
                        // Child Checks
+                       "nth-child": "jQuery.sibling(a,m[3]).cur",
                        "first-child": "jQuery.sibling(a,0).cur",
                        "last-child": "jQuery.sibling(a,0).last",
                        "only-child": "jQuery.sibling(a).length==1",
@@ -1025,7 +1295,8 @@ jQuery.extend({
                        // Form elements
                        enabled: "!a.disabled",
                        disabled: "a.disabled",
-                       checked: "a.checked"
+                       checked: "a.checked",
+                       selected: "a.selected"
                },
                ".": "jQuery.className.has(a,m[2])",
                "@": {
@@ -1089,7 +1360,7 @@ jQuery.extend({
         * @test t( "Adjacent", "p + p", ["ap","en","sap"] );
         * @test t( "Comma, Child, and Adjacent", "a + a, code > a", ["groups","anchor1","anchor2"] );
         * @test t( "First Child", "p:first-child", ["firstp","sndp"] );
-   * @test t( "Attribute Exists", "a[@title]", ["google"] );
+        * @test t( "Attribute Exists", "a[@title]", ["google"] );
         * @test t( "Attribute Exists", "*[@title]", ["google"] );
         * @test t( "Attribute Exists", "[@title]", ["google"] );
         * @test t( "Attribute Equals", "a[@rel='bookmark']", ["simon1"] );
@@ -1141,8 +1412,10 @@ jQuery.extend({
         * @test t( "Is Visible", "input:visible", ["text1","text2","radio1","radio2","check1","check2"] );
         * @test t( "Is Hidden", "input:hidden", ["hidden1","hidden2"] );
         *
-        * @name jQuery.find
+        * @name $.find
+        * @type Array<Element>
         * @private
+        * @cat Core
         */
        find: function( t, context ) {
                // Make sure that the context is a DOM Element
@@ -1178,6 +1451,8 @@ jQuery.extend({
                        var foundToken = false;
                        
                        for ( var i = 0; i < jQuery.token.length; i += 2 ) {
+                               if ( foundToken ) continue;
+
                                var re = new RegExp("^(" + jQuery.token[i] + ")");
                                var m = re.exec(t);
                                
@@ -1214,8 +1489,9 @@ jQuery.extend({
                                                        );
                                        }
                                }
-                       }
        
+                       }
+
                        if ( t ) {
                                var val = jQuery.filter(t,r);
                                ret = r = val.r;
@@ -1240,28 +1516,29 @@ jQuery.extend({
                return r;
        },
        
-       attr: function(o,a,v){
-               if ( a && a.constructor == String ) {
-                       var fix = {
-                               "for": "htmlFor",
-                               "class": "className",
-                               "float": "cssFloat"
-                       };
-                       
-                       a = (fix[a] && fix[a].replace && fix[a] || a)
-                               .replace(/-([a-z])/ig,function(z,b){
-                                       return b.toUpperCase();
-                               });
-                       
-                       if ( v != undefined ) {
-                               o[a] = v;
-                               if ( o.setAttribute && a != "disabled" )
-                                       o.setAttribute(a,v);
-                       }
-                       
-                       return o[a] || o.getAttribute && o.getAttribute(a) || "";
-               } else
-                       return "";
+       attr: function(elem, name, value){
+               var fix = {
+                       "for": "htmlFor",
+                       "class": "className",
+                       "float": "cssFloat",
+                       innerHTML: "innerHTML",
+                       className: "className",
+                       value: "value",
+                       disabled: "disabled",
+                       checked: "checked"
+               };
+
+               if ( fix[name] ) {
+                       if ( value != undefined ) elem[fix[name]] = value;
+                       return elem[fix[name]];
+               } else if ( elem.getAttribute ) {
+                       if ( value != undefined ) elem.setAttribute( name, value );
+                       return elem.getAttribute( name, 2 );
+               } else {
+                       name = name.replace(/-([a-z])/ig,function(z,b){return b.toUpperCase();});
+                       if ( value != undefined ) elem[name] = value;
+                       return elem[name];
+               }
        },
 
        // The regular expressions that power the parsing engine
@@ -1340,10 +1617,10 @@ jQuery.extend({
        /**
         * Remove the whitespace from the beginning and end of a string.
         *
-        * @private
-        * @name jQuery.trim
+        * @name $.trim
         * @type String
         * @param String str The string to trim.
+        * @cat Javascript
         */
        trim: function(t){
                return t.replace(/^\s+|\s+$/g, "");
@@ -1353,80 +1630,84 @@ jQuery.extend({
         * All ancestors of a given element.
         *
         * @private
-        * @name jQuery.parents
+        * @name $.parents
         * @type Array<Element>
         * @param Element elem The element to find the ancestors of.
+        * @cat DOM/Traversing
         */
-       parents: function(a){
-               var b = [];
-               var c = a.parentNode;
-               while ( c && c != document ) {
-                       b.push( c );
-                       c = c.parentNode;
+       parents: function( elem ){
+               var matched = [];
+               var cur = elem.parentNode;
+               while ( cur && cur != document ) {
+                       matched.push( cur );
+                       cur = cur.parentNode;
                }
-               return b;
+               return matched;
        },
        
        /**
         * All elements on a specified axis.
         *
         * @private
-        * @name jQuery.sibling
+        * @name $.sibling
         * @type Array
         * @param Element elem The element to find all the siblings of (including itself).
+        * @cat DOM/Traversing
         */
-       sibling: function(a,n) {
-               var type = [];
-               var tmp = a.parentNode.childNodes;
-               for ( var i = 0; i < tmp.length; i++ ) {
-                       if ( tmp[i].nodeType == 1 )
-                               type.push( tmp[i] );
-                       if ( tmp[i] == a )
-                               type.n = type.length - 1;
+       sibling: function(elem, pos, not) {
+               var elems = [];
+
+               var siblings = elem.parentNode.childNodes;
+               for ( var i = 0; i < siblings.length; i++ ) {
+                       if ( not === true && siblings[i] == elem ) continue;
+
+                       if ( siblings[i].nodeType == 1 )
+                               elems.push( siblings[i] );
+                       if ( siblings[i] == elem )
+                               elems.n = elems.length - 1;
                }
-               type.last = type.n == type.length - 1;
-               type.cur =
-                       n == "even" && type.n % 2 == 0 ||
-                       n == "odd" && type.n % 2 ||
-                       type[n] == a;
-               type.prev = type[type.n - 1];
-               type.next = type[type.n + 1];
-               return type;
+
+               return jQuery.extend( elems, {
+                       last: elems.n == elems.length - 1,
+                       cur: pos == "even" && elems.n % 2 == 0 || pos == "odd" && elems.n % 2 || elems[pos] == elem,
+                       prev: elems[elems.n - 1],
+                       next: elems[elems.n + 1]
+               });
        },
        
        /**
         * Merge two arrays together, removing all duplicates.
         *
-        * @private
-        * @name jQuery.merge
+        * @name $.merge
         * @type Array
         * @param Array a The first array to merge.
         * @param Array b The second array to merge.
+        * @cat Javascript
         */
-       merge: function(a,b) {
-               var d = [];
+       merge: function(first, second) {
+               var result = [];
                
                // Move b over to the new array (this helps to avoid
                // StaticNodeList instances)
-               for ( var k = 0; k < a.length; k++ )
-                       d[k] = a[k];
+               for ( var k = 0; k < first.length; k++ )
+                       result[k] = first[k];
        
                // Now check for duplicates between a and b and only
                // add the unique items
-               for ( var i = 0; i < b.length; i++ ) {
-                       var c = true;
+               for ( var i = 0; i < second.length; i++ ) {
+                       var noCollision = true;
                        
                        // The collision-checking process
-                       for ( var j = 0; j < a.length; j++ )
-                               if ( b[i] == a[j] )
-                                       c = false;
+                       for ( var j = 0; j < first.length; j++ )
+                               if ( second[i] == first[j] )
+                                       noCollision = false;
                                
                        // If the item is unique, add it
-                       if ( c )
-                               d.push( b[i] );
+                       if ( noCollision )
+                               result.push( second[i] );
                }
        
-               return d;
+               return result;
        },
        
        /**
@@ -1434,28 +1715,28 @@ jQuery.extend({
         * in to this method will be passed two arguments: 'a' (which is the
         * array item) and 'i' (which is the index of the item in the array).
         *
-        * @private
-        * @name jQuery.grep
+        * @name $.grep
         * @type Array
         * @param Array array The Array to find items in.
         * @param Function fn The function to process each item against.
         * @param Boolean inv Invert the selection - select the opposite of the function.
+        * @cat Javascript
         */
-       grep: function(a,f,s) {
+       grep: function(elems, fn, inv) {
                // If a string is passed in for the function, make a function
                // for it (a handy shortcut)
-               if ( f.constructor == String )
-                       f = new Function("a","i","return " + f);
+               if ( fn.constructor == String )
+                       fn = new Function("a","i","return " + fn);
                        
-               var r = [];
+               var result = [];
                
                // Go through the array, only saving the items
                // that pass the validator function
-               for ( var i = 0; i < a.length; i++ )
-                       if ( !s && f(a[i],i) || s && !f(a[i],i) )
-                               r.push( a[i] );
+               for ( var i = 0; i < elems.length; i++ )
+                       if ( !inv && fn(elems[i],i) || inv && !fn(elems[i],i) )
+                               result.push( elems[i] );
                
-               return r;
+               return result;
        },
        
        /**
@@ -1466,30 +1747,32 @@ jQuery.extend({
         * from the array. Both of these changes imply that the size of the array may not
         * be the same size upon completion, as it was when it started.
         *
-        * @private
-        * @name jQuery.map
+        * @name $.map
         * @type Array
         * @param Array array The Array to translate.
         * @param Function fn The function to process each item against.
+        * @cat Javascript
         */
-       map: function(a,f) {
+       map: function(elems, fn) {
                // If a string is passed in for the function, make a function
                // for it (a handy shortcut)
-               if ( f.constructor == String )
-                       f = new Function("a","return " + f);
+               if ( fn.constructor == String )
+                       fn = new Function("a","return " + fn);
                
-               var r = [];
+               var result = [];
                
                // Go through the array, translating each of the items to their
                // new value (or values).
-               for ( var i = 0; i < a.length; i++ ) {
-                       var t = f(a[i],i);
-                       if ( t !== null && t != undefined ) {
-                               if ( t.constructor != Array ) t = [t];
-                               r = jQuery.merge( r, t );
+               for ( var i = 0; i < elems.length; i++ ) {
+                       var val = fn(elems[i],i);
+
+                       if ( val !== null && val != undefined ) {
+                               if ( val.constructor != Array ) val = [val];
+                               result = jQuery.merge( result, val );
                        }
                }
-               return r;
+
+               return result;
        },
        
        /*
@@ -1625,7 +1908,7 @@ new function() {
                safari: /webkit/.test(b),
                opera: /opera/.test(b),
                msie: /msie/.test(b) && !/opera/.test(b),
-               mozilla: /mozilla/.test(b) && !/compatible/.test(b)
+               mozilla: /mozilla/.test(b) && !/(compatible|webkit)/.test(b)
        };
 
        // Check to see if the W3C box model is being used
@@ -1915,8 +2198,8 @@ jQuery.macros = {
         * Get the current CSS background of the first matched element.
         * 
         * @example $("p").background();
-        * @before <p>This is just a test.</p>
-        * @result ""
+        * @before <p style="background:blue;">This is just a test.</p>
+        * @result "blue"
         *
         * @name background
         * @type String
@@ -1937,6 +2220,64 @@ jQuery.macros = {
         */
        
        css: "width,height,top,left,position,float,overflow,color,background".split(","),
+       
+       /**
+        * Reduce the set of matched elements to a single element.
+        * The position of the element in the set of matched elements
+        * starts at 0 and goes to length - 1.
+        * 
+        * @example $("p").eq(1)
+        * @before <p>This is just a test.</p><p>So is this</p>
+        * @result [ <p>So is this</p> ]
+        *
+        * @name eq
+        * @type jQuery
+        * @param Number pos The index of the element that you wish to limit to.
+        * @cat Core
+        */
+        
+       /**
+        * Reduce the set of matched elements to all elements before a given position.
+        * The position of the element in the set of matched elements
+        * starts at 0 and goes to length - 1.
+        * 
+        * @example $("p").lt(1)
+        * @before <p>This is just a test.</p><p>So is this</p>
+        * @result [ <p>This is just a test.</p> ]
+        *
+        * @name lt
+        * @type jQuery
+        * @param Number pos Reduce the set to all elements below this position.
+        * @cat Core
+        */
+        
+       /**
+        * Reduce the set of matched elements to all elements after a given position.
+        * The position of the element in the set of matched elements
+        * starts at 0 and goes to length - 1.
+        * 
+        * @example $("p").gt(0)
+        * @before <p>This is just a test.</p><p>So is this</p>
+        * @result [ <p>So is this</p> ]
+        *
+        * @name gt
+        * @type jQuery
+        * @param Number pos Reduce the set to all elements after this position.
+        * @cat Core
+        */
+        
+       /**
+        * Filter the set of elements to those that contain the specified text.
+        * 
+        * @example $("p").contains("test")
+        * @before <p>This is just a test.</p><p>So is this</p>
+        * @result [ <p>This is just a test.</p> ]
+        *
+        * @name contains
+        * @type jQuery
+        * @param String str The string that will be contained within the text of an element.
+        * @cat DOM/Traversing
+        */
 
        filter: [ "eq", "lt", "gt", "contains" ],
 
@@ -2189,7 +2530,7 @@ jQuery.macros = {
 
                /**
                 * Get a set of elements containing the unique ancestors of the matched
-                * set of elements.
+                * set of elements (except for the root element).
                 *
                 * @example $("span").ancestors()
                 * @before <html><body><div><p><span>Hello</span></p><span>Hello Again</span></div></body></html>
@@ -2217,7 +2558,7 @@ jQuery.macros = {
                
                /**
                 * Get a set of elements containing the unique ancestors of the matched
-                * set of elements.
+                * set of elements (except for the root element).
                 *
                 * @example $("span").ancestors()
                 * @before <html><body><div><p><span>Hello</span></p><span>Hello Again</span></div></body></html>
@@ -2362,10 +2703,27 @@ jQuery.macros = {
                 * @param String expr An expression to filter the child Elements with
                 * @cat DOM/Traversing
                 */
-               children: "a.childNodes"
+               children: "jQuery.sibling(a.firstChild)"
        },
 
        each: {
+
+               /**
+                * Remove an attribute from each of the matched elements.
+                *
+                * @example $("input").removeAttr("disabled")
+                * @before <input disabled="disabled"/>
+                * @result <input/>
+                *
+                * @name removeAttr
+                * @type jQuery
+                * @param String name The name of the attribute to remove.
+                * @cat DOM
+                */
+               removeAttr: function( key ) {
+                       this.removeAttribute( key );
+               },
+
                /**
                 * Displays each of the set of matched elements if they are hidden.
                 * 
@@ -2383,7 +2741,7 @@ jQuery.macros = {
                 * @type jQuery
                 * @cat Effects
                 */
-               _show: function(){
+               show: function(){
                        this.style.display = this.oldblock ? this.oldblock : "";
                        if ( jQuery.css(this,"display") == "none" )
                                this.style.display = "block";
@@ -2406,7 +2764,7 @@ jQuery.macros = {
                 * @type jQuery
                 * @cat Effects
                 */
-               _hide: function(){
+               hide: function(){
                        this.oldblock = this.oldblock || jQuery.css(this,"display");
                        if ( this.oldblock == "none" )
                                this.oldblock = "block";
@@ -2426,9 +2784,8 @@ jQuery.macros = {
                 * @type jQuery
                 * @cat Effects
                 */
-               _toggle: function(){
-                       var d = jQuery.css(this,"display");
-                       $(this)[ !d || d == "none" ? "show" : "hide" ]();
+               toggle: function(){
+                       jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ].apply( jQuery(this), arguments );
                },
                
                /**
@@ -2524,7 +2881,7 @@ jQuery.macros = {
                 * @cat DOM/Manipulation
                 */
                remove: function(a){
-                       if ( !a || jQuery.filter( [this], a ).r )
+                       if ( !a || jQuery.filter( a, [this] ).r )
                                this.parentNode.removeChild( this );
                },
        
@@ -2572,7 +2929,7 @@ jQuery.macros = {
                 */
                bind: function( type, fn ) {
                        if ( fn.constructor == String )
-                               fn = new Function("e", ( !fn.indexOf(".") ? "$(this)" : "return " ) + fn);
+                               fn = new Function("e", ( !fn.indexOf(".") ? "jQuery(this)" : "return " ) + fn);
                        jQuery.event.add( this, type, fn );
                },
                
@@ -2638,3 +2995,5 @@ jQuery.macros = {
                }
        }
 };
+
+jQuery.init();