X-Git-Url: http://git.asbjorn.it/?a=blobdiff_plain;ds=inline;f=src%2Fjquery%2Fjquery.js;h=b01038766ff64b58fe5d4bf1f372cb64cb55ffda;hb=2b82ffbbfac419e017acea3e0f83c063549e545e;hp=30fd03d282d62957fe88a4f5f1302f947007e966;hpb=d7b73ea5c7440c49c804b3cafe67e84aafbdd064;p=jquery.git diff --git a/src/jquery/jquery.js b/src/jquery/jquery.js index 30fd03d..b010387 100644 --- a/src/jquery/jquery.js +++ b/src/jquery/jquery.js @@ -23,39 +23,41 @@ window.undefined = window.undefined; * @cat Core */ var jQuery = function(a,c) { + // If the context is global, return a new object + if ( window == this ) + return new jQuery(a,c); + // Make sure that a selection was provided a = a || document; + // HANDLE: $(function) // Shortcut for document ready // Safari reports typeof on DOM NodeLists as a function - if ( typeof a == "function" && !a.nodeType && a[0] == undefined ) - return jQuery(document)[ jQuery.fn.ready ? "ready" : "load" ]( a ); - - // Watch for when a jQuery object is passed as the selector - if ( a.jquery ) - return jQuery( jQuery.makeArray( a ) ); - - // Watch for when a jQuery object is passed at the context - if ( c && c.jquery ) - return jQuery( c ).find(a); - - // If the context is global, return a new object - if ( window == this ) - return new jQuery(a,c); - + if ( jQuery.isFunction(a) && !a.nodeType && a[0] == undefined ) + return new jQuery(document)[ jQuery.fn.ready ? "ready" : "load" ]( a ); + // Handle HTML strings if ( typeof a == "string" ) { + // HANDLE: $(html) -> $(array) var m = /^[^<]*(<.+>)[^>]*$/.exec(a); - if ( m ) a = jQuery.clean( [ m[1] ] ); + if ( m ) + a = jQuery.clean( [ m[1] ] ); + + // HANDLE: $(expr) + else + return new jQuery( c ).find( a ); } + + return this.setArray( + // HANDLE: $(array) + a.constructor == Array && a || - // Watch for when an array is passed in - return this.setArray( a.constructor == Array || a.length && a != window && !a.nodeType && a[0] != undefined && a[0].nodeType ? - // Assume that it is an array of DOM Elements - jQuery.makeArray( a ) : + // HANDLE: $(arraylike) + // Watch for when an array-like object is passed as the selector + (a.jquery || a.length && a != window && !a.nodeType && a[0] != undefined && a[0].nodeType) && jQuery.makeArray( a ) || - // Find the matching elements and save them for later - jQuery.find( a, c ) ); + // HANDLE: $(*) + [ a ] ); }; // Map over the $ in case of overwrite @@ -152,25 +154,18 @@ var $ = jQuery; * }); * @desc Executes the function 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 cloned copy of a jQuery object. This function - * copies the set of matched elements from one jQuery object and creates - * another, new, jQuery object containing the same elements. - * - * @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' (as would normally be the case if a simple div.find("p") was done). + * @example jQuery(function($) { + * // Your code using failsafe $ alias here... + * }); + * @desc Uses both the shortcut for $(document).ready() and the argument + * to write failsafe jQuery code using the $ alias, without relying on the + * global alias. * * @name $ - * @param jQuery obj The jQuery object to be cloned. + * @param Function fn The function to execute when the DOM is ready. * @cat Core * @type jQuery + * @see ready(Function) */ jQuery.fn = jQuery.prototype = { @@ -258,16 +253,16 @@ jQuery.fn = jQuery.prototype = { * Set the jQuery object to an array of elements, while maintaining * the stack. * - * @example $("img").set([ document.body ]); - * @result $("img").set() == [ document.body ] + * @example $("img").pushStack([ document.body ]); + * @result $("img").pushStack() == [ document.body ] * * @private - * @name set + * @name pushStack * @type jQuery * @param Elements elems An array of elements * @cat Core */ - set: function( a ) { + pushStack: function( a ) { var ret = jQuery(this); ret.prevObject = this; return ret.setArray( a ); @@ -275,7 +270,7 @@ jQuery.fn = jQuery.prototype = { /** * Set the jQuery object to an array of elements. This operation is - * completely destructive - be sure to use .set() if you wish to maintain + * completely destructive - be sure to use .pushStack() if you wish to maintain * the jQuery stack. * * @example $("img").setArray([ document.body ]); @@ -388,6 +383,8 @@ jQuery.fn = jQuery.prototype = { /** * Set a single property to a value, on all matched elements. * + * Can compute values provided as ${formula}, see second example. + * * Note that you can't set the name property of input elements in IE. * Use $(html) or .append(html) or .html(html) to create elements * on the fly including the name property. @@ -397,35 +394,55 @@ jQuery.fn = jQuery.prototype = { * @result * @desc Sets src attribute to all images. * + * @example $("img").attr("title", "${this.src}"); + * @before + * @result + * @desc Sets title attribute from src attribute, a shortcut for attr(String,Function) + * * @name attr * @type jQuery * @param String key The name of the property to set. * @param Object value The value to set the property to. * @cat DOM/Attributes */ + + /** + * Set a single property to a computed value, on all matched elements. + * + * Instead of a value, a function is provided, that computes the value. + * + * @example $("img").attr("title", function() { return this.src }); + * @before + * @result + * @desc Sets title attribute from src attribute. + * + * @name attr + * @type jQuery + * @param String key The name of the property to set. + * @param Function value A function returning the value to set. + * @cat DOM/Attributes + */ attr: function( key, value, type ) { + var obj = key; + + // Look for the case where we're accessing a style value + if ( key.constructor == String ) + if ( value == undefined ) + return jQuery[ type || "attr" ]( this[0], key ); + else { + obj = {}; + obj[ key ] = value; + } + // Check to see if we're setting style values - return typeof key != "string" || value != undefined ? - this.each(function(){ - // See if we're setting a hash of styles - if ( value == undefined ) - // Set all the styles - for ( var prop in key ) - jQuery.attr( - type ? this.style : this, - prop, key[prop] - ); - - // See if we're setting a single key/value style - else - jQuery.attr( - type ? this.style : this, - key, value - ); - }) : - - // Look for the case where we're accessing a style value - jQuery[ type || "attr" ]( this[0], key ); + return this.each(function(){ + // Set all the styles + for ( var prop in obj ) + jQuery.attr( + type ? this.style : this, + prop, jQuery.prop(this, obj[prop], type) + ); + }); }, /** @@ -468,16 +485,22 @@ jQuery.fn = jQuery.prototype = { /** * Set a single style property to a value, on all matched elements. + * If a number is provided, it is automatically converted into a pixel value. * * @example $("p").css("color","red"); * @before
Test Paragraph.
* @resultTest Paragraph.
* @desc Changes the color of all paragraphs to red * + * @example $("p").css("left",30); + * @beforeTest Paragraph.
+ * @resultTest Paragraph.
+ * @desc Changes the left of all paragraphs to "30px" + * * @name css * @type jQuery * @param String key The name of the property to set. - * @param Object value The value to set the property to. + * @param String|Number value The value to set the property to. * @cat CSS */ css: function( key, value ) { @@ -500,10 +523,17 @@ jQuery.fn = jQuery.prototype = { */ /** - * Set the text contents of all matched elements. This has the same - * effect as html(). + * Set the text contents of all matched elements. + * + * Similar to html(), but escapes HTML (replace "<" and ">" with their + * HTML entities). * - * @example $("p").text("Some new text."); + * @example $("p").text("Some new text."); + * @beforeTest Paragraph.
+ * @result<b>Some</b> new text.
+ * @desc Sets the text of all paragraphs. + * + * @example $("p").text("Some new text.", true); * @beforeTest Paragraph.
* @resultSome new text.
* @desc Sets the text of all paragraphs. @@ -514,21 +544,12 @@ jQuery.fn = jQuery.prototype = { * @cat DOM/Attributes */ text: function(e) { - // A surprisingly high number of people expect the - // .text() method to do this, so lets do it! - if ( typeof e == "string" ) - return this.html( e ); - - e = e || this; - var t = ""; - for ( var j = 0, el = e.length; j < el; j++ ) { - var r = e[j].childNodes; - for ( var i = 0, rl = r.length; i < rl; i++ ) - if ( r[i].nodeType != 8 ) - t += r[i].nodeType != 1 ? - r[i].nodeValue : jQuery.fn.text([ r[i] ]); - } - return t; + var type = this.length && this[0].innerText == undefined ? + "textContent" : "innerText"; + + return e == undefined ? + jQuery.map(this, function(a){ return a[ type ]; }).join("") : + this.each(function(){ this[ type ] = e; }); }, /** @@ -742,7 +763,7 @@ jQuery.fn = jQuery.prototype = { * @example $("p").find("span").end(); * @beforeHello, how are you?
* @result [...
] - * desc Selects all paragraphs, finds span elements inside these, and reverts the + * @desc Selects all paragraphs, finds span elements inside these, and reverts the * selection back to the paragraphs. * * @name end @@ -774,7 +795,7 @@ jQuery.fn = jQuery.prototype = { * @cat DOM/Traversing */ find: function(t) { - return this.set( jQuery.map( this, function(a){ + return this.pushStack( jQuery.map( this, function(a){ return jQuery.find(t,a); }) ); }, @@ -792,10 +813,11 @@ jQuery.fn = jQuery.prototype = { * * @name clone * @type jQuery + * @param Boolean deep (Optional) Set to false if you don't want to clone all descendant nodes, in addition to the element itself. * @cat DOM/Manipulation */ clone: function(deep) { - return this.set( jQuery.map( this, function(a){ + return this.pushStack( jQuery.map( this, function(a){ return a.cloneNode( deep != undefined ? deep : true ); }) ); }, @@ -805,21 +827,21 @@ jQuery.fn = jQuery.prototype = { * match the specified expression(s). This method is used to narrow down * the results of a search. * - * Provide a String array of expressions to apply multiple filters at once. + * Provide a comma-separated list of expressions to apply multiple filters at once. * * @example $("p").filter(".selected") * @beforeHello
How are you?
* @result [Hello
] * @desc Selects all paragraphs and removes those without a class "selected". * - * @example $("p").filter([".selected", ":first"]) + * @example $("p").filter(".selected, :first") * @beforeHello
Hello Again
And Again
* @result [Hello
,And Again
] * @desc Selects all paragraphs and removes those without class "selected" and being the first one. * * @name filter * @type jQuery - * @param String|ArrayHello
Hello Again
Hello
] + * @desc Removes all elements that match "div p.selected" from the total set of all paragraphs. + * + * @name not + * @type jQuery + * @param jQuery elems A set of elements to remove from the jQuery set of matched elements. + * @cat DOM/Traversing + */ not: function(t) { - return this.set( typeof t == "string" ? - jQuery.filter(t,this,true).r : - jQuery.grep(this,function(a){ return a != t; }) ); + return this.pushStack( + t.constructor == String && + jQuery.multiFilter(t,this,true) || + + jQuery.grep(this,function(a){ + if ( t.constructor == Array || t.jquery ) + return jQuery.inArray( t, a ) < 0; + else + return a != t; + }) ); }, /** - * Adds the elements matched by the expression to the jQuery object. This - * can be used to concatenate the result sets of two expressions. + * Adds more elements, matched by the given expression, + * to the set of matched elements. * * @example $("p").add("span") - * @beforeHello
Hello Again
+ * @beforeHello
Hello Again * @result [Hello
, Hello Again ] * * @name add @@ -908,19 +944,31 @@ jQuery.fn = jQuery.prototype = { * @param String expr An expression whose matched elements are added * @cat DOM/Traversing */ + + /** + * Adds more elements, created on the fly, to the set of + * matched elements. + * + * @example $("p").add("Again") + * @beforeHello
+ * @result [Hello
, Again ] + * + * @name add + * @type jQuery + * @param String html A string of HTML to create on the fly. + * @cat DOM/Traversing + */ /** * Adds one or more Elements to the set of matched elements. * - * This is used to add a set of Elements to a jQuery object. - * * @example $("p").add( document.getElementById("a") ) * @beforeHello
Hello Again
* @result [Hello
, Hello Again ] * - * @example $("p").add([document.getElementById("a"), document.getElementById("b")]) - * @beforeHello
Hello AgainAnd Again
- * @result [Hello
, Hello Again, And Again ] + * @example $("p").add( document.forms[0].elements ) + * @beforeHello
+ * @result [Hello
, , ] * * @name add * @type jQuery @@ -928,10 +976,10 @@ jQuery.fn = jQuery.prototype = { * @cat DOM/Traversing */ add: function(t) { - return this.set( jQuery.merge( - this.get(), typeof t == "string" ? - jQuery.find(t) : - t.constructor == Array ? t : [t] ) ); + return this.pushStack( jQuery.merge( + this.get(), + typeof t == "string" ? jQuery(t).get() : t ) + ); }, /** @@ -987,7 +1035,9 @@ jQuery.fn = jQuery.prototype = { * @cat DOM/Attributes */ val: function( val ) { - return val == undefined ? ( this.length ? this[0].value : null ) : this.attr( "value", val ); + return val == undefined ? + ( this.length ? this[0].value : null ) : + this.attr( "value", val ); }, /** @@ -1017,7 +1067,9 @@ jQuery.fn = jQuery.prototype = { * @cat DOM/Attributes */ html: function( val ) { - return val == undefined ? ( this.length ? this[0].innerHTML : null ) : this.attr( "innerHTML", val ); + return val == undefined ? + ( this.length ? this[0].innerHTML : null ) : + this.empty().append( val ); }, /** @@ -1159,21 +1211,31 @@ jQuery.extend({ $ = jQuery._$; }, + isFunction: function( fn ) { + return fn && typeof fn == "function"; + }, + /** * A generic iterator function, which can be used to seemlessly * iterate over both objects and arrays. This function is not the same * as $().each() - which is used to iterate, exclusively, over a jQuery * object. This function can be used to iterate over anything. * - * @example $.each( [0,1,2], function(i){ - * alert( "Item #" + i + ": " + this ); + * The callback has two arguments:the key (objects) or index (arrays) as first + * the first, and the value as the second. + * + * @example $.each( [0,1,2], function(i, n){ + * alert( "Item #" + i + ": " + n ); * }); - * @desc Iterates over the items in an array, accessing both the current item and its index. + * @desc This is an example of iterating over the items in an array, + * accessing both the current item and its index. * - * @example $.each( { name: "John", lang: "JS" }, function(i){ - * alert( "Name: " + i + ", Value: " + this ); + * @example $.each( { name: "John", lang: "JS" }, function(i, n){ + * alert( "Name: " + i + ", Value: " + n ); * }); - * @desc Iterates over the properties in an Object, accessing both the current item and its key. + * + * @desc This is an example of iterating over the properties in an + * Object, accessing both the current item and its key. * * @name $.each * @param Object obj The object, or array, to iterate over. @@ -1191,22 +1253,40 @@ jQuery.extend({ if ( fn.apply( obj[i], args || [i, obj[i]] ) === false ) break; return obj; }, + + prop: function(elem, value, type){ + // Handle executable functions + if ( jQuery.isFunction( value ) ) + return value.call( elem ); + + // Handle passing in a number to a CSS property + if ( value.constructor == Number && type == "curCSS" ) + return value + "px"; + + return value; + }, className: { + // internal only, use addClass("class") add: function( elem, c ){ jQuery.each( c.split(/\s+/), function(i, cur){ if ( !jQuery.className.has( elem.className, cur ) ) elem.className += ( elem.className ? " " : "" ) + cur; }); }, + + // internal only, use removeClass("class") remove: function( elem, c ){ - elem.className = c ? - jQuery.grep( elem.className.split(/\s+/), function(cur){ - return !jQuery.className.has( c, cur ); - }).join(' ') : ""; + elem.className = c ? + jQuery.grep( elem.className.split(/\s+/), function(cur){ + return !jQuery.className.has( c, cur ); + }).join(" ") : ""; }, - has: function( classes, c ){ - return classes && new RegExp("(^|\\s)" + c + "(\\s|$)").test( classes ); + + // internal only, use is(".class") + has: function( t, c ) { + t = t.className || t; + return t && new RegExp("(^|\\s)" + c + "(\\s|$)").test( t ); } }, @@ -1267,17 +1347,16 @@ jQuery.extend({ curCSS: function(elem, prop, force) { var ret; - if (prop == 'opacity' && jQuery.browser.msie) - return jQuery.attr(elem.style, 'opacity'); + if (prop == "opacity" && jQuery.browser.msie) + return jQuery.attr(elem.style, "opacity"); if (prop == "float" || prop == "cssFloat") prop = jQuery.browser.msie ? "styleFloat" : "cssFloat"; - if (!force && elem.style[prop]) { - + if (!force && elem.style[prop]) ret = elem.style[prop]; - } else if (document.defaultView && document.defaultView.getComputedStyle) { + else if (document.defaultView && document.defaultView.getComputedStyle) { if (prop == "cssFloat" || prop == "styleFloat") prop = "float"; @@ -1287,12 +1366,12 @@ jQuery.extend({ if ( cur ) ret = cur.getPropertyValue(prop); - else if ( prop == 'display' ) - ret = 'none'; + else if ( prop == "display" ) + ret = "none"; else - jQuery.swap(elem, { display: 'block' }, function() { - var c = document.defaultView.getComputedStyle(this, ''); - ret = c && c.getPropertyValue(prop) || ''; + jQuery.swap(elem, { display: "block" }, function() { + var c = document.defaultView.getComputedStyle(this, ""); + ret = c && c.getPropertyValue(prop) || ""; }); } else if (elem.currentStyle) { @@ -1307,51 +1386,69 @@ jQuery.extend({ clean: function(a) { var r = []; + for ( var i = 0, al = a.length; i < al; i++ ) { var arg = a[i]; - if ( typeof arg == "string" ) { // Convert html string into DOM nodes + + if ( !arg ) continue; + + if ( arg.constructor == Number ) + arg = arg.toString(); + + // Convert html string into DOM nodes + if ( typeof arg == "string" ) { // Trim whitespace, otherwise indexOf won't work as expected - var s = jQuery.trim(arg), s3 = s.substring(0,3), s6 = s.substring(0,6), - div = document.createElement("div"), wrap = [0,"",""]; - - if ( s.substring(0,4) == "