X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fjquery%2Fjquery.js;h=686c20d7bfd69d4b78886792a88aa2bd41ac4ea6;hb=6f7cd669597cbcf026886074fb31963fe767e2b3;hp=829ef4a17b21474d3d4acd287e7ffb8df6aef212;hpb=feabeb8572979f7888bd73e80f436bece1448e5a;p=jquery.git diff --git a/src/jquery/jquery.js b/src/jquery/jquery.js index 829ef4a..686c20d 100644 --- a/src/jquery/jquery.js +++ b/src/jquery/jquery.js @@ -1,5 +1,5 @@ /* - * jQuery - New Wave Javascript + * jQuery @VERSION - New Wave Javascript * * Copyright (c) 2006 John Resig (jquery.com) * Dual licensed under the MIT (MIT-LICENSE.txt) @@ -28,7 +28,7 @@ window.undefined = window.undefined; * @name jQuery * @cat Core */ -jQuery = function(a,c) { +var jQuery = function(a,c) { // Shortcut for document ready (because $(document).each() is silly) if ( a && typeof a == "function" && jQuery.fn.ready ) @@ -50,8 +50,10 @@ jQuery = function(a,c) { return new jQuery(a,c); // Handle HTML strings - var m = /^[^<]*(<.+>)[^>]*$/.exec(a); - if ( m ) a = jQuery.clean( [ m[1] ] ); + if ( a.constructor == String ) { + var m = /^[^<]*(<.+>)[^>]*$/.exec(a); + if ( m ) a = jQuery.clean( [ m[1] ] ); + } // Watch for when an array is passed in this.get( a.constructor == Array || a.length && !a.nodeType && a[0] != undefined && a[0].nodeType ? @@ -61,12 +63,14 @@ jQuery = function(a,c) { // Find the matching elements and save them for later jQuery.find( a, c ) ); - // See if an extra function was provided + // See if an extra function was provided var fn = arguments[ arguments.length - 1 ]; // If so, execute it in context if ( fn && typeof fn == "function" ) this.each(fn); + + return this; }; // Map over the $ in case of overwrite @@ -95,7 +99,10 @@ if ( typeof $ != "undefined" ) * @result [

two

] * * @example $("

Hello

").appendTo("#body") - * @desc Creates a div element (and all of its contents) dynamically, and appends it to the element with the ID of body. + * @desc Creates a div element (and all of its contents) dynamically, + * and appends it to the element with the ID of body. Internally, an + * element is created and it's innerHTML property set to the given markup. + * It is therefore both quite flexible and limited. * * @name $ * @param String expr An expression to search with, or a string of HTML to create on the fly. @@ -154,6 +161,7 @@ if ( typeof $ != "undefined" ) * behaves just like $(document).ready(), in that it should be used to wrap * all of the other $() operations on your page. While this function is, * technically, chainable - there really isn't much use for chaining against it. + * You can have as many $(document).ready events on your page as you like. * * @example $(function(){ * // Document is ready @@ -186,7 +194,7 @@ var $ = jQuery; jQuery.fn = jQuery.prototype = { /** - * The current SVN version of jQuery. + * The current version of jQuery. * * @private * @property @@ -194,7 +202,7 @@ jQuery.fn = jQuery.prototype = { * @type String * @cat Core */ - jquery: "$Rev$", + jquery: "@VERSION", /** * The number of elements currently matched. @@ -391,8 +399,8 @@ jQuery.fn = jQuery.prototype = { * ok( $('#simon').attr('class') == "blog link", 'Check for class attribute' ); * ok( $('#name').attr('name') == "name", 'Check for name attribute' ); * ok( $('#text1').attr('name') == "action", 'Check for name attribute' ); - * ok( $('#form').attr('action') == "formaction", 'Check for action attribute' ); - * + * ok( $('#form').attr('action').indexOf("formaction") >= 0, 'Check for action attribute' ); + * * @name attr * @type Object * @param String name The name of the property to access. @@ -442,6 +450,17 @@ jQuery.fn = jQuery.prototype = { * $("#check2").attr('checked', false); * ok( document.getElementById('check2').checked == false, 'Set checked attribute' ); * + * @test stop(); + * $.get('data/dashboard.xml', function(xml) { + * var titles = []; + * $('tab', xml).each(function() { + * titles.push($(this).attr('title')); + * }); + * ok( titles[0] == 'Location', 'attr() in XML context: Check first title' ); + * ok( titles[1] == 'Users', 'attr() in XML context: Check second title' ); + * start(); + * }); + * * @name attr * @type jQuery * @param String key The name of the property to set. @@ -493,7 +512,7 @@ jQuery.fn = jQuery.prototype = { * representation of itself. Eg. fontWeight, fontSize, fontFamily, borderWidth, * borderStyle, borderBottomWidth etc. * - * @test ok( $('#foo').css("display") == 'block', 'Check for css property "display"'); + * @test ok( $('#main').css("display") == 'none', 'Check for css property "display"'); * * @name css * @type Object @@ -515,6 +534,14 @@ jQuery.fn = jQuery.prototype = { * ok( !$('#foo').is(':visible'), 'Modified CSS display: Assert element is hidden'); * $('#foo').css({display: 'block'}); * ok( $('#foo').is(':visible'), 'Modified CSS display: Assert element is visible'); + * $('#floatTest').css({styleFloat: 'right'}); + * ok( $('#floatTest').css('styleFloat') == 'right', 'Modified CSS float using "styleFloat": Assert float is right'); + * $('#floatTest').css({cssFloat: 'left'}); + * ok( $('#floatTest').css('cssFloat') == 'left', 'Modified CSS float using "cssFloat": Assert float is left'); + * $('#floatTest').css({'float': 'right'}); + * ok( $('#floatTest').css('cssFloat') == 'right', 'Modified CSS float using "cssFloat": Assert float is right'); + * $('#floatTest').css({'font-size': '30px'}); + * ok( $('#floatTest').css('font-size') == '30px', 'Modified CSS font-size: Assert font-size is 30px'); * * @name css * @type jQuery @@ -536,6 +563,14 @@ jQuery.fn = jQuery.prototype = { * ok( !$('#foo').is(':visible'), 'Modified CSS display: Assert element is hidden'); * $('#foo').css('display', 'block'); * ok( $('#foo').is(':visible'), 'Modified CSS display: Assert element is visible'); + * $('#floatTest').css('styleFloat', 'left'); + * ok( $('#floatTest').css('styleFloat') == 'left', 'Modified CSS float using "styleFloat": Assert float is left'); + * $('#floatTest').css('cssFloat', 'right'); + * ok( $('#floatTest').css('cssFloat') == 'right', 'Modified CSS float using "cssFloat": Assert float is right'); + * $('#floatTest').css('float', 'left'); + * ok( $('#floatTest').css('cssFloat') == 'left', 'Modified CSS float using "cssFloat": Assert float is left'); + * $('#floatTest').css('font-size', '20px'); + * ok( $('#floatTest').css('font-size') == '20px', 'Modified CSS font-size: Assert font-size is 20px'); * * @name css * @type jQuery @@ -644,7 +679,7 @@ jQuery.fn = jQuery.prototype = { // Insert it before the element to be wrapped this.parentNode.insertBefore( b, this ); - // Find he deepest point in the wrap structure + // Find the deepest point in the wrap structure while ( b.firstChild ) b = b.firstChild; @@ -667,12 +702,6 @@ jQuery.fn = jQuery.prototype = { * var result = $('#first').append('buga'); * ok( result.text() == defaultText + 'buga', 'Check if text appending works' ); * - * 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. @@ -982,6 +1011,12 @@ jQuery.fn = jQuery.prototype = { * @result $("p").filter(".selected") == [

Hello

] * * @test isSet( $("input").filter(":checked").get(), q("radio2", "check1"), "Filter elements" ); + * @test $("input").filter(":checked",function(i){ + * ok( this == q("radio2", "check1")[i], "Filter elements, context" ); + * }); + * @test $("#main > p#ap > a").filter("#foobar",function(){},function(i){ + * ok( this == q("google","groups", "mark")[i], "Filter elements, else context" ); + * }); * * @name filter * @type jQuery @@ -1014,6 +1049,7 @@ jQuery.fn = jQuery.prototype = { for ( var i = 0; i < t.length; i++ ) if ( jQuery.filter(t[i],[a]).r.length ) return a; + return false; }) || t.constructor == Boolean && @@ -1160,52 +1196,6 @@ jQuery.fn = jQuery.prototype = { }, /** - * Executes the first callback for every element that fits the expression - * and executes the second callback for every element that does not fit - * the expression. - * - * @example $('div').ifelse(':visible', - * function() { $(this).slideUp(); }, - function() { $(this).slideDown(); } - * ); - * @desc Slides down all visible div elements and slides down all others - * - * @test var checked = 0, notChecked = 0; - * var inputChecked = $(':input').ifelse(':checked', - * function() { checked++; }, - * function() { notChecked++ } - * ); - * ok( checked == 2, 'Check is if/else: Count checked elements' ); - * ok( notChecked == 12, 'Check is if/else: Count unchecked elements' ); - * - * $('#first, #foo, #ap').ifelse('p', - * function() { $(this).html('me == p') }, - * function() { $(this).html('me != p') } - * ); - * ok( $('#first').text() == 'me == p', 'Check filter-if-clause' ); - * ok( $('#foo').text() == 'me != p', 'Check else-clause' ); - * ok( $('#ap').text() == 'me == p', 'Check filter-if-clause' ); - * - * @name ifelse - * @type jQuery - * @param String expression The expression with which to filter - * @param Function ifCallback Called for elements that fit the expression - * @param Function elseCallback Called for elements that don't fit the expression - * @cat DOM/Traversing - */ - ifelse: function(expr, ifCallback, elseCallback) { - var ifCallback = ifCallback || function() {}; - var elseCalllback = elseCallback || function() {}; - return this.each(function() { - if($(this).is(expr)) { - ifCallback.apply(this); - } else { - elseCallback.apply(this); - } - }); - }, - - /** * * * @private @@ -1253,17 +1243,23 @@ jQuery.fn = jQuery.prototype = { */ pushStack: function(a,args) { var fn = args && args[args.length-1]; + var fn2 = args && args[args.length-2]; + + if ( fn && fn.constructor != Function ) fn = null; + if ( fn2 && fn2.constructor != Function ) fn2 = null; - if ( !fn || fn.constructor != Function ) { + if ( !fn ) { if ( !this.stack ) this.stack = []; this.stack.push( this.get() ); this.get( a ); } else { var old = this.get(); this.get( a ); - if ( typeof fn == "function" ) - this.each( fn ); - this.get( old ); + + if ( fn2 && a.length || !fn2 ) + this.each( fn2 || fn ).get( old ); + else + this.get( old ).each( fn ); } return this; @@ -1317,8 +1313,17 @@ jQuery.fn = jQuery.prototype = { * @cat Javascript */ jQuery.extend = jQuery.fn.extend = function(obj,prop) { + // Watch for the case where null or undefined gets passed in by accident + if ( arguments.length > 1 && (prop === null || prop == undefined) ) + return obj; + + // If no property object was provided, then we're extending jQuery if ( !prop ) { prop = obj; obj = this; } + + // Extend the base object for ( var i in prop ) obj[i] = prop[i]; + + // Return the modified object return obj; }; @@ -1410,7 +1415,7 @@ jQuery.extend({ fn.apply( obj[i], args || [i, obj[i]] ); else for ( var i = 0; i < obj.length; i++ ) - fn.apply( obj[i], args || [i, obj[i]] ); + if ( fn.apply( obj[i], args || [i, obj[i]] ) === false ) break; return obj; }, @@ -1420,10 +1425,6 @@ jQuery.extend({ o.className += ( o.className ? " " : "" ) + c; }, remove: function(o,c){ - /* - o.className = !c ? "" : - o.className.replace( - new RegExp("(^|\\s*\\b[^-])"+c+"($|\\b(?=[^-]))", "g"), "");*/ if( !c ) { o.className = ""; } else { @@ -1491,14 +1492,19 @@ jQuery.extend({ }); return p == "height" ? oHeight : oWidth; - } else if ( p == "opacity" && jQuery.browser.msie ) - return parseFloat( jQuery.curCSS(e,"filter").replace(/[^0-9.]/,"") ) || 1; + } return jQuery.curCSS( e, p ); }, curCSS: function(elem, prop, force) { var ret; + + 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]) { @@ -1511,6 +1517,9 @@ jQuery.extend({ } else if (document.defaultView && document.defaultView.getComputedStyle) { + if (prop == "cssFloat" || prop == "styleFloat") + prop = "float"; + prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase(); var cur = document.defaultView.getComputedStyle(elem, null); @@ -1532,7 +1541,9 @@ jQuery.extend({ var r = []; for ( var i = 0; i < a.length; i++ ) { if ( a[i].constructor == String ) { - + // trim whitespace, otherwise indexOf won't work as expected + a[i] = jQuery.trim(a[i]); + var table = ""; if ( !a[i].indexOf("=0", + contains: "jQuery.fn.text.apply([a]).indexOf(m[3])>=0", // Visibility visible: "a.type!='hidden'&&jQuery.css(a,'display')!='none'&&jQuery.css(a,'visibility')!='hidden'", @@ -1601,7 +1612,7 @@ jQuery.extend({ enabled: "!a.disabled", disabled: "a.disabled", checked: "a.checked", - selected: "a.selected", + selected: "a.selected || jQuery.attr(a, 'selected')", // Form elements text: "a.type=='text'", @@ -1681,9 +1692,9 @@ jQuery.extend({ * t( "Attribute Exists", "*[@title]", ["google"] ); * t( "Attribute Exists", "[@title]", ["google"] ); * - * t( "Non-existing part of attribute [@name*=bla]", "[@name*=bla]", [] ); - * t( "Non-existing start of attribute [@name^=bla]", "[@name^=bla]", [] ); - * t( "Non-existing end of attribute [@name$=bla]", "[@name$=bla]", [] ); + * t( "Non-existing part of attribute", "[@name*=bla]", [] ); + * t( "Non-existing start of attribute", "[@name^=bla]", [] ); + * t( "Non-existing end of attribute", "[@name$=bla]", [] ); * * t( "Attribute Equals", "a[@rel='bookmark']", ["simon1"] ); * t( "Attribute Equals", 'a[@rel="bookmark"]', ["simon1"] ); @@ -1860,22 +1871,39 @@ jQuery.extend({ var fix = { "for": "htmlFor", "class": "className", - "float": "cssFloat", + "float": jQuery.browser.msie ? "styleFloat" : "cssFloat", + cssFloat: jQuery.browser.msie ? "styleFloat" : "cssFloat", innerHTML: "innerHTML", className: "className", value: "value", disabled: "disabled", checked: "checked" }; + + // IE actually uses filters for opacity ... elem is actually elem.style + if (name == "opacity" && jQuery.browser.msie && value != undefined) { + // IE has trouble with opacity if it does not have layout + // Would prefer to check element.hasLayout first but don't have access to the element here + elem['zoom'] = 1; + if (value == 1) // Remove filter to avoid more IE weirdness + return elem["filter"] = elem["filter"].replace(/alpha\([^\)]*\)/gi,""); + else + return elem["filter"] = elem["filter"].replace(/alpha\([^\)]*\)/gi,"") + "alpha(opacity=" + value * 100 + ")"; + } else if (name == "opacity" && jQuery.browser.msie) { + return elem["filter"] ? parseFloat( elem["filter"].match(/alpha\(opacity=(.*)\)/)[1] )/100 : 1; + } + + // Mozilla doesn't play well with opacity 1 + if (name == "opacity" && jQuery.browser.mozilla && value == 1) value = 0.9999; if ( fix[name] ) { if ( value != undefined ) elem[fix[name]] = value; return elem[fix[name]]; - } else if( value == undefined && $.browser.msie && elem.nodeName && elem.nodeName.toUpperCase() == 'FORM' && (name == 'action' || name == 'method') ) { + } else if( value == undefined && jQuery.browser.msie && elem.nodeName && elem.nodeName.toUpperCase() == 'FORM' && (name == 'action' || name == 'method') ) { return elem.getAttributeNode(name).nodeValue; - } else if ( elem.getAttribute != undefined ) { + } else if ( elem.getAttribute != undefined && elem.tagName ) { // IE elem.getAttribute passes even for style if ( value != undefined ) elem.setAttribute( name, value ); - return elem.getAttribute( name, 2 ); + return elem.getAttribute( name ); } else { name = name.replace(/-([a-z])/ig,function(z,b){return b.toUpperCase();}); if ( value != undefined ) elem[name] = value; @@ -1886,13 +1914,13 @@ jQuery.extend({ // The regular expressions that power the parsing engine parse: [ // Match: [@value='test'], [@foo] - "\\[ *(@)S *([!*$^=]*)Q\\]", + "\\[ *(@)S *([!*$^=]*) *('?\"?)(.*?)\\4 *\\]", // Match: [div], [div p] - "(\\[)Q\\]", + "(\\[)\s*(.*?)\s*\\]", // Match: :contains('foo') - "(:)S\\(Q\\)", + "(:)S\\(\"?'?([^\\)]*?)\"?'?\\)", // Match: :even, :last-chlid "([:.#]*)S" @@ -1908,28 +1936,19 @@ jQuery.extend({ var p = jQuery.parse; for ( var i = 0; i < p.length; i++ ) { - // 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', " *('|\"|)([^'\"]*?)\\"+br+" *" ), "i" ); + + // Look for, and replace, string-like sequences + // and finally build a regexp out of it + var re = new RegExp( + "^" + p[i].replace("S", "([a-z*_-][a-z0-9_-]*)"), "i" ); var m = re.exec( t ); if ( m ) { - // Re-organize the match - if(br == 4){ + // Re-organize the first match + if ( !i ) 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, "" ); @@ -2245,12 +2264,12 @@ jQuery.extend({ }, handle: function(event) { - if ( typeof jQuery == "undefined" ) return; + if ( typeof jQuery == "undefined" ) return false; event = event || jQuery.event.fix( window.event ); // If no correct event was found, fail - if ( !event ) return; + if ( !event ) return false; var returnValue = true; @@ -2706,7 +2725,7 @@ jQuery.macros = { /** * Set the value of every matched element. * - * @example $("input").value("test"); + * @example $("input").val("test"); * @before * @result *