Added tests for children()
[jquery.git] / src / jquery / jquery.js
index 9b9cfa4..a0d8775 100644 (file)
@@ -28,7 +28,7 @@ window.undefined = window.undefined;
  * @name jQuery
  * @cat Core
  */
-function jQuery(a,c) {
+jQuery = function(a,c) {
 
        // Shortcut for document ready (because $(document).each() is silly)
        if ( a && a.constructor == Function && jQuery.fn.ready )
@@ -67,7 +67,7 @@ function jQuery(a,c) {
        // If so, execute it in context
        if ( fn && fn.constructor == Function )
                this.each(fn);
-}
+};
 
 // Map over the $ in case of overwrite
 if ( typeof $ != "undefined" )
@@ -203,7 +203,7 @@ jQuery.fn = jQuery.prototype = {
         * @before <img src="test1.jpg"/> <img src="test2.jpg"/>
         * @result 2
         *
-        * @test cmpOK( $("div").length, "==", 2, "Get Number of Elements Found" );
+        * @test ok( $("div").length == 2, "Get Number of Elements Found" );
         *
         * @property
         * @name length
@@ -218,7 +218,7 @@ jQuery.fn = jQuery.prototype = {
         * @before <img src="test1.jpg"/> <img src="test2.jpg"/>
         * @result 2
         *
-        * @test cmpOK( $("div").size(), "==", 2, "Get Number of Elements Found" );
+        * @test ok( $("div").size() == 2, "Get Number of Elements Found" );
         *
         * @name size
         * @type Number
@@ -252,7 +252,7 @@ jQuery.fn = jQuery.prototype = {
         * @before <img src="test1.jpg"/> <img src="test2.jpg"/>
         * @result [ <img src="test1.jpg"/> ]
         *
-        * @test cmpOK( $("div").get(0), "==", document.getElementById("main"), "Get A Single Element" );
+        * @test ok( $("div").get(0) == document.getElementById("main"), "Get A Single Element" );
         *
         * @name get
         * @type Element
@@ -390,6 +390,8 @@ jQuery.fn = jQuery.prototype = {
         * @test ok( $('#en').attr('lang') == "en", 'Check for lang attribute' );
         * @test ok( $('#simon').attr('class') == "blog link", 'Check for class attribute' );
         * @test ok( $('#name').attr('name') == "name", 'Check for name attribute' );
+        * @test ok( $('#text1').attr('name') == "action", 'Check for name attribute' );
+        * @test ok( $('#form').attr('action') == "formaction", 'Check for action attribute' );
         * 
         * @name attr
         * @type Object
@@ -585,19 +587,17 @@ jQuery.fn = jQuery.prototype = {
         * and finds the deepest ancestor element within its
         * structure - it is that element that will en-wrap everything else.
         *
+        * This does not work with elements that contain text. Any necessary text
+        * must be added after the wrapping is done.
+        *
         * @example $("p").wrap("<div class='wrap'></div>");
         * @before <p>Test Paragraph.</p>
         * @result <div class='wrap'><p>Test Paragraph.</p></div>
         * 
         * @test var defaultText = 'Try them out:'
         * var result = $('#first').wrap('<div class="red"><span></span></div>').text();
-        * ok( defaultText == result, 'Check for simple wrapping' );
-        * ok( $('#first').parent().parent().is('.red'), 'Check if wrapper div has class "red"' );
-        *
-        * @test var defaultText = 'Try them out:'
-        * var result = $('#first').wrap('<div class="red">xx<span></span>yy</div>').text()
-        * ok( 'xx' + defaultText + 'yy' == result, 'Check for wrapping' );
-        * ok( $('#first').parent().parent().is('.red'), 'Check if wrapper div has class "red"' );
+        * ok( defaultText == result, 'Check for wrapping of on-the-fly html' );
+        * ok( $('#first').parent().parent().is('.red'), 'Check if wrapper has class "red"' );
         *
         * @name wrap
         * @type jQuery
@@ -615,9 +615,17 @@ jQuery.fn = jQuery.prototype = {
         * 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>
-        * @result <div class='wrap'><p>Test Paragraph.</p></div>
+        * This does not work with elements that contain text. Any necessary text
+        * must be added after the wrapping is done.
+        *
+        * @example $("p").wrap( document.getElementById('content') );
+        * @before <p>Test Paragraph.</p><div id="content"></div>
+        * @result <div id="content"><p>Test Paragraph.</p></div>
+        *
+        * @test var defaultText = 'Try them out:'
+        * var result = $('#first').wrap(document.getElementById('empty')).parent();
+        * ok( result.is('ol'), 'Check for element wrapping' );
+        * ok( result.text() == defaultText, 'Check for element wrapping' );
         *
         * @name wrap
         * @type jQuery
@@ -659,6 +667,12 @@ jQuery.fn = jQuery.prototype = {
         * var result = $('#first').append('<b>buga</b>');
         * ok( result.text() == defaultText + 'buga', 'Check if text appending works' );
         *
+        * @test reset();
+        * var expected = "Try them out: bla ";
+        * $('#first').append(" ");
+        * $('#first').append("bla ");
+        * ok( expected == $('#first').text(), "Check for appending of spaces" );
+        *
         * @name append
         * @type jQuery
         * @param String html A string of HTML, that will be created on the fly and appended to the target.
@@ -1033,7 +1047,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")
+        * @test ok($("#main > p#ap > a").not("#google").length == 2, ".not")
         *
         * @name not
         * @type jQuery
@@ -1163,7 +1177,7 @@ jQuery.fn = jQuery.prototype = {
                return this.each(function(){
                        var obj = this;
 
-                       if ( table && this.nodeName == "TABLE" && a[0].nodeName != "THEAD" ) {
+                       if ( table && this.nodeName.toUpperCase() == "TABLE" && a[0].nodeName.toUpperCase() != "THEAD" ) {
                                var tbody = this.getElementsByTagName("tbody");
 
                                if ( !tbody.length ) {
@@ -1210,7 +1224,20 @@ jQuery.fn = jQuery.prototype = {
 };
 
 /**
- *
+ * Extends the jQuery object itself. Can be used to add both static
+ * functions and plugin methods.
+ * 
+ * @example $.fn.extend({
+ *   check: function() {
+ *     this.each(function() { this.checked = true; });
+ *   ),
+ *   uncheck: function() {
+ *     this.each(function() { this.checked = false; });
+ *   }
+ * });
+ * $("input[@type=checkbox]").check();
+ * $("input[@type=radio]").uncheck();
+ * @desc Adds two plugin methods.
  *
  * @private
  * @name extend
@@ -1510,19 +1537,31 @@ jQuery.extend({
                        visible: "a.type!='hidden'&&jQuery.css(a,'display')!='none'&&jQuery.css(a,'visibility')!='hidden'",
                        hidden: "a.type=='hidden'||jQuery.css(a,'display')=='none'||jQuery.css(a,'visibility')=='hidden'",
 
-                       // Form elements
+                       // Form attributes
                        enabled: "!a.disabled",
                        disabled: "a.disabled",
                        checked: "a.checked",
-                       selected: "a.selected"
+                       selected: "a.selected",
+
+                       // Form elements
+                       text: "a.type=='text'",
+                       radio: "a.type=='radio'",
+                       checkbox: "a.type=='checkbox'",
+                       file: "a.type=='file'",
+                       password: "a.type=='password'",
+                       submit: "a.type=='submit'",
+                       image: "a.type=='image'",
+                       reset: "a.type=='reset'",
+                       button: "a.type=='button'",
+                       input: "a.nodeName.toLowerCase()=='input'||a.nodeName.toLowerCase()=='select'||a.nodeName.toLowerCase()=='textarea'"
                },
                ".": "jQuery.className.has(a,m[2])",
                "@": {
                        "=": "z==m[4]",
                        "!=": "z!=m[4]",
-                       "^=": "!z.indexOf(m[4])",
-                       "$=": "z.substr(z.length - m[4].length,m[4].length)==m[4]",
-                       "*=": "z.indexOf(m[4])>=0",
+                       "^=": "z && !z.indexOf(m[4])",
+                       "$=": "z && z.substr(z.length - m[4].length,m[4].length)==m[4]",
+                       "*=": "z && z.indexOf(m[4])>=0",
                        "": "z"
                },
                "[": "jQuery.find(m[2],a).length"
@@ -1547,7 +1586,7 @@ jQuery.extend({
         * @test t( "Element Selector", "div", ["main","foo"] );
         * @test t( "Element Selector", "body", ["body"] );
         * @test t( "Element Selector", "html", ["html"] );
-        * @test cmpOK( $("*").size(), ">=", 30, "Element Selector" );
+        * @test ok( $("*").size() >= 30, "Element Selector" );
         * @test t( "Parent Element", "div div", ["foo"] );
         *
         * @test t( "ID Selector", "#body", ["body"] );
@@ -1581,6 +1620,11 @@ jQuery.extend({
         * @test t( "Attribute Exists", "a[@title]", ["google"] );
         * @test t( "Attribute Exists", "*[@title]", ["google"] );
         * @test t( "Attribute Exists", "[@title]", ["google"] );
+        * 
+        * @test t( "Non-existing part of attribute [@name*=bla]", "[@name*=bla]", [] ); 
+        * @test t( "Non-existing start of attribute [@name^=bla]", "[@name^=bla]", [] ); 
+        * @test t( "Non-existing end of attribute [@name$=bla]", "[@name$=bla]", [] ); 
+        *
         * @test t( "Attribute Equals", "a[@rel='bookmark']", ["simon1"] );
         * @test t( "Attribute Equals", 'a[@rel="bookmark"]', ["simon1"] );
         * @test t( "Attribute Equals", "a[@rel=bookmark]", ["simon1"] );
@@ -1604,7 +1648,7 @@ jQuery.extend({
         * @test t( "Element Preceded By", "p ~ div", ["foo"] );
         * @test t( "Not", "a.blog:not(.link)", ["mark"] );
         *
-        * @test cmpOK( jQuery.find("//*").length, ">=", 30, "All Elements (//*)" );
+        * @test ok( jQuery.find("//*").length >= 30, "All Elements (//*)" );
         * @test t( "All Div Elements", "//div", ["main","foo"] );
         * @test t( "Absolute Path", "/html/body", ["body"] );
         * @test t( "Absolute Path w/ *", "/* /body", ["body"] );
@@ -1631,6 +1675,20 @@ jQuery.extend({
         * @test t( "Is Visible", "input:visible", ["text1","text2","radio1","radio2","check1","check2","name"] );
         * @test t( "Is Hidden", "input:hidden", ["hidden1","hidden2"] );
         *
+        * @test t( "Grouped Form Elements", "input[@name='foo[bar]']", ["hidden2"] );
+        *
+        * @test t( "All Children of ID", "#foo/*", ["sndp", "en", "sap"]  );
+        * @test t( "All Children of ID with no children", "#firstUL/*", []  );
+        *
+        * @test t( "Form element :input", ":input", ["text1", "text2", "radio1", "radio2", "check1", "check2", "hidden1", "hidden2", "name", "area1", "select1", "select2", "select3"] );
+        * @test t( "Form element :radio", ":radio", ["radio1", "radio2"] );
+        * @test t( "Form element :checkbox", ":checkbox", ["check1", "check2"] );
+        * @test t( "Form element :text", ":text", ["text1", "text2", "hidden2", "name"] );
+        *
+        * @test t( ":not() Existing attribute", "input:not([@name])", ["text2", "check2"]);
+        * @test t( ":not() Equals attribute", "select:not([@name=select1])", ["select2", "select3"]);
+        * @test t( ":not() Equals quoted attribute", "select:not([@name='select1'])", ["select2", "select3"]);
+        *
         * @name $.find
         * @type Array<Element>
         * @private
@@ -1763,16 +1821,16 @@ jQuery.extend({
        // The regular expressions that power the parsing engine
        parse: [
                // Match: [@value='test'], [@foo]
-               [ "\\[ *(@)S *([!*$^=]*) *Q\\]", 1 ],
+               "\\[ *(@)S *([!*$^=]*)Q\\]",
 
                // Match: [div], [div p]
-               [ "(\\[)Q\\]", 0 ],
+               "(\\[)Q\\]",
 
                // Match: :contains('foo')
-               [ "(:)S\\(Q\\)", 0 ],
+               "(:)S\\(Q\\)",
 
                // Match: :even, :last-chlid
-               [ "([:.#]*)S", 0 ]
+               "([:.#]*)S"
        ],
 
        filter: function(t,r,not) {
@@ -1785,21 +1843,28 @@ jQuery.extend({
                        var p = jQuery.parse;
 
                        for ( var i = 0; i < p.length; i++ ) {
-                               var re = new RegExp( "^" + p[i][0]
-
+                               // get number for backreference
+                               var br = 0;
+                               if(p[i].indexOf('Q') != -1){
+                                       br = p[i].replace(/\\\(/g,'').match(/\(|S/g).length+1;
+                               }
+                               var re = new RegExp( "^" + p[i]
+                       
                                        // Look for a string-like sequence
                                        .replace( 'S', "([a-z*_-][a-z0-9_-]*)" )
 
                                        // Look for something (optionally) enclosed with quotes
-                                       .replace( 'Q', " *'?\"?([^'\"]*?)'?\"? *" ), "i" );
+                                       .replace( 'Q', " *('|\"|)([^'\"]*?)\\"+br+" *" ), "i" );
 
                                var m = re.exec( t );
 
                                if ( m ) {
                                        // Re-organize the match
-                                       if ( p[i][1] )
-                                               m = ["", m[1], m[3], m[2], m[4]];
-
+                                       if(br == 4){
+                                               m = ["",m[1], m[3], m[2], m[5]];
+                                       } else if(br != 0) {
+                                               m.splice(br,1);
+                                       }
                                        // Remove what we just matched
                                        t = t.replace( re, "" );
 
@@ -1878,15 +1943,17 @@ jQuery.extend({
         */
        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;
+               
+               if(elem) {
+                       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;
+                       }
                }
 
                return jQuery.extend( elems, {
@@ -2124,8 +2191,11 @@ jQuery.extend({
 
                        var c = this.events[event.type];
 
+                       var args = [].slice.call( arguments, 1 );
+                       args.unshift( event );
+
                        for ( var j in c ) {
-                               if ( c[j].apply( this, [event] ) === false ) {
+                               if ( c[j].apply( this, args ) === false ) {
                                        event.preventDefault();
                                        event.stopPropagation();
                                        returnValue = false;
@@ -2609,6 +2679,10 @@ jQuery.macros = {
                 * @before <input type="text" id="test" value="some text"/>
                 * @result "test"
                 *
+                * @test ok( $(document.getElementById('main')).id() == "main", "Check for id" );
+                * @test ok( $("#foo").id() == "foo", "Check for id" );
+                * @test ok( !$("head").id(), "Check for id" );
+                *
                 * @name id
                 * @type String
                 * @cat DOM/Attributes
@@ -2635,6 +2709,9 @@ jQuery.macros = {
                 * @before <img src="test.jpg" title="my image"/>
                 * @result "my image"
                 *
+                * @test ok( $(document.getElementById('google')).title() == "Google!", "Check for title" );
+                * @test ok( !$("#yahoo").title(), "Check for title" );
+                *
                 * @name title
                 * @type String
                 * @cat DOM/Attributes
@@ -2661,6 +2738,10 @@ jQuery.macros = {
                 * @before <input type="text" name="username"/>
                 * @result "username"
                 *
+                * @test ok( $(document.getElementById('text1')).name() == "action", "Check for name" );
+                * @test ok( $("#hidden1").name() == "hidden", "Check for name" );
+                * @test ok( !$("#area1").name(), "Check for name" );
+                *
                 * @name name
                 * @type String
                 * @cat DOM/Attributes
@@ -2916,6 +2997,8 @@ jQuery.macros = {
                 * @before <p>Hello</p><div><span>Hello Again</span></div><p>And Again</p>
                 * @result [ <p>Hello</p>, <p>And Again</p> ]
                 *
+                * @test isSet( $("#en").siblings().get(), q("sndp", "sap"), "Check for siblings" ); 
+                *
                 * @name siblings
                 * @type jQuery
                 * @cat DOM/Traversing
@@ -2929,12 +3012,15 @@ jQuery.macros = {
                 * @before <div><span>Hello</span></div><p class="selected">Hello Again</p><p>And Again</p>
                 * @result [ <p class="selected">Hello Again</p> ]
                 *
+                * @test isSet( $("#sndp").siblings("[code]").get(), q("sap"), "Check for filtered siblings (has code child element)" ); 
+                * @test isSet( $("#sndp").siblings("[a]").get(), q("en", "sap"), "Check for filtered siblings (has anchor child element)" );
+                *
                 * @name siblings
                 * @type jQuery
                 * @param String expr An expression to filter the sibling Elements with
                 * @cat DOM/Traversing
                 */
-               siblings: jQuery.sibling,
+               siblings: "jQuery.sibling(a, null, true)",
 
 
                /**
@@ -2945,6 +3031,8 @@ jQuery.macros = {
                 * @before <p>Hello</p><div><span>Hello Again</span></div><p>And Again</p>
                 * @result [ <span>Hello Again</span> ]
                 *
+                * @test isSet( $("#foo").children().get(), q("sndp", "en", "sap"), "Check for children" );
+                *
                 * @name children
                 * @type jQuery
                 * @cat DOM/Traversing
@@ -2958,6 +3046,8 @@ jQuery.macros = {
                 * @before <div><span>Hello</span><p class="selected">Hello Again</p><p>And Again</p></div>
                 * @result [ <p class="selected">Hello Again</p> ]
                 *
+                * @test isSet( $("#foo").children("[code]").get(), q("sndp", "sap"), "Check for filtered children" ); 
+                *
                 * @name children
                 * @type jQuery
                 * @param String expr An expression to filter the child Elements with