Fixed bug #180 as suggested, changing xxx.constructor == Function to typeof xxx ...
[jquery.git] / src / jquery / jquery.js
index 69628b3..9f2189e 100644 (file)
@@ -31,7 +31,7 @@ window.undefined = window.undefined;
 jQuery = function(a,c) {
 
        // Shortcut for document ready (because $(document).each() is silly)
-       if ( a && a.constructor == Function && jQuery.fn.ready )
+       if ( a && typeof a == "function" && jQuery.fn.ready )
                return jQuery(document).ready(a);
 
        // Make sure that a selection was provided
@@ -65,7 +65,7 @@ jQuery = function(a,c) {
        var fn = arguments[ arguments.length - 1 ];
 
        // If so, execute it in context
-       if ( fn && fn.constructor == Function )
+       if ( fn && typeof fn == "function" )
                this.each(fn);
 };
 
@@ -587,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
@@ -617,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
@@ -661,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.
@@ -1007,7 +1019,7 @@ jQuery.fn = jQuery.prototype = {
                        t.constructor == Boolean &&
                        ( t ? this.get() : [] ) ||
 
-                       t.constructor == Function &&
+                       typeof t == "function" &&
                        jQuery.grep( this, t ) ||
 
                        jQuery.filter(t,this).r, arguments );
@@ -1165,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 ) {
@@ -1202,7 +1214,7 @@ jQuery.fn = jQuery.prototype = {
                } else {
                        var old = this.get();
                        this.get( a );
-                       if ( fn.constructor == Function )
+                       if ( typeof fn == "function" )
                                this.each( fn );
                        this.get( old );
                }
@@ -1212,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
@@ -1348,9 +1373,22 @@ jQuery.extend({
                        o.className += ( o.className ? " " : "" ) + c;
                },
                remove: function(o,c){
+                       /*
                        o.className = !c ? "" :
                                o.className.replace(
-                                       new RegExp("(^|\\s*\\b[^-])"+c+"($|\\b(?=[^-]))", "g"), "");
+                                       new RegExp("(^|\\s*\\b[^-])"+c+"($|\\b(?=[^-]))", "g"), "");*/
+                       if( !c ) {
+                               o.className = "";
+                       } else {
+                               var classes = o.className.split(" ");
+                               for(var i=0; i<classes.length; i++) {
+                                       if(classes[i] == c) {
+                                               classes.splice(i, 1);
+                                               break;
+                                       }
+                               }
+                               o.className = classes.join(' ');
+                       }
                },
                has: function(e,a) {
                        if ( e.className != undefined )
@@ -1512,11 +1550,23 @@ 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])",
                "@": {
@@ -1643,6 +1693,18 @@ jQuery.extend({
         * @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( "Form element :radio:checked", ":radio:checked", ["radio2"] );
+        * @test t( "Form element :checkbox:checked", ":checkbox:checked", ["check1"] );
+        * @test t( "Form element :checkbox:checked, :radio:checked", ":checkbox:checked, :radio:checked", ["check1", "radio2"] );
+        *
+        * @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
@@ -1897,15 +1959,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, {
@@ -2631,6 +2695,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
@@ -2657,6 +2725,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
@@ -2683,6 +2754,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
@@ -2961,7 +3036,7 @@ jQuery.macros = {
                 * @param String expr An expression to filter the sibling Elements with
                 * @cat DOM/Traversing
                 */
-               siblings: jQuery.sibling,
+               siblings: "jQuery.sibling(a, null, true)",
 
 
                /**
@@ -2972,6 +3047,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
@@ -2985,6 +3062,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
@@ -3114,6 +3193,14 @@ jQuery.macros = {
                 * }
                 * ok( pass, "Remove Class" );
                 *
+                * @test var div = $("div").addClass("test").addClass("foo").addClass("bar");
+                * div.removeClass("test").removeClass("bar").removeClass("foo");
+                * var pass = true;
+                * for ( var i = 0; i < div.size(); i++ ) {
+                *  if ( div.get(i).className.match(/test|bar|foo/) ) pass = false;
+                * }
+                * ok( pass, "Remove multiple classes" );
+                *
                 * @name removeClass
                 * @type jQuery
                 * @param String class A CSS class to remove from the elements