diff options
author | jeresig <jeresig@gmail.com> | 2011-04-10 15:41:51 -0400 |
---|---|---|
committer | jeresig <jeresig@gmail.com> | 2011-04-10 15:41:51 -0400 |
commit | b92d2f0bc96d65c83252fa3033c37b92eb32d442 (patch) | |
tree | ac8545d23de62865406703eb3eb7ff3bd7401d75 | |
parent | d4e4414451e15d23d7174e8eeddaa952ed0e4d73 (diff) | |
parent | 3a1b4661f5b8249ce7a741084824ec5445c75719 (diff) | |
download | jquery-b92d2f0bc96d65c83252fa3033c37b92eb32d442.tar.gz jquery-b92d2f0bc96d65c83252fa3033c37b92eb32d442.zip |
Merge branch 'attrhooks.1.6v2' of https://github.com/timmywil/jquery into timmywil-attrhooks.1.6v2
Conflicts:
src/attributes.js
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | .gitmodules | 6 | ||||
-rw-r--r-- | Makefile | 66 | ||||
-rw-r--r-- | src/ajax.js | 9 | ||||
-rw-r--r-- | src/attributes.js | 216 | ||||
-rw-r--r-- | src/core.js | 2 | ||||
-rw-r--r-- | src/css.js | 25 | ||||
-rw-r--r-- | src/deferred.js | 5 | ||||
-rw-r--r-- | src/event.js | 34 | ||||
-rw-r--r-- | src/manipulation.js | 9 | ||||
-rw-r--r-- | src/offset.js | 9 | ||||
m--------- | src/sizzle | 0 | ||||
-rw-r--r-- | src/support.js | 36 | ||||
-rw-r--r-- | test/data/offset/fixed.html | 1 | ||||
-rw-r--r-- | test/index.html | 4 | ||||
m--------- | test/qunit | 0 | ||||
-rw-r--r-- | test/unit/ajax.js | 12 | ||||
-rw-r--r-- | test/unit/attributes.js | 227 | ||||
-rw-r--r-- | test/unit/css.js | 12 | ||||
-rw-r--r-- | test/unit/event.js | 44 | ||||
-rw-r--r-- | test/unit/manipulation.js | 13 | ||||
-rw-r--r-- | test/unit/offset.js | 17 | ||||
-rw-r--r-- | version.txt | 2 |
23 files changed, 508 insertions, 243 deletions
diff --git a/.gitignore b/.gitignore index a77d67a96..6cd547974 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,5 @@ dist *~ *.diff *.patch -test/qunit -src/sizzle /*.html .DS_Store diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..19c60418e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "src/sizzle"] + path = src/sizzle + url = git://github.com/jquery/sizzle.git +[submodule "test/qunit"] + path = test/qunit + url = git://github.com/jquery/qunit.git @@ -1,5 +1,3 @@ -V ?= 0 - SRC_DIR = src TEST_DIR = test BUILD_DIR = build @@ -38,48 +36,21 @@ JQ = ${DIST_DIR}/jquery.js JQ_MIN = ${DIST_DIR}/jquery.min.js SIZZLE_DIR = ${SRC_DIR}/sizzle -QUNIT_DIR = ${TEST_DIR}/qunit JQ_VER = $(shell cat version.txt) VER = sed "s/@VERSION/${JQ_VER}/" DATE=$(shell git log -1 --pretty=format:%ad) -all: jquery min lint +all: update_submodules core + +core: jquery min lint @@echo "jQuery build complete." ${DIST_DIR}: @@mkdir -p ${DIST_DIR} -ifeq ($(strip $(V)),0) -verbose = --quiet -else ifeq ($(strip $(V)),1) -verbose = -else -verbose = --verbose -endif - -define clone_or_pull --@@if test ! -d $(strip ${1})/.git; then \ - echo "Cloning $(strip ${1})..."; \ - git clone $(strip ${verbose}) --depth=1 $(strip ${2}) $(strip ${1}); \ - else \ - echo "Pulling $(strip ${1})..."; \ - git --git-dir=$(strip ${1})/.git pull $(strip ${verbose}) origin master; \ - fi - -endef - -${QUNIT_DIR}: - $(call clone_or_pull, ${QUNIT_DIR}, git://github.com/jquery/qunit.git) - -${SIZZLE_DIR}: - $(call clone_or_pull, ${SIZZLE_DIR}, git://github.com/jeresig/sizzle.git) - -init: ${QUNIT_DIR} ${SIZZLE_DIR} - -jquery: init ${JQ} -jq: init ${JQ} +jquery: ${JQ} ${JQ}: ${MODULES} | ${DIST_DIR} @@echo "Building" ${JQ} @@ -102,9 +73,9 @@ lint: jquery echo "You must have NodeJS installed in order to test jQuery against JSLint."; \ fi -min: ${JQ_MIN} +min: jquery ${JQ_MIN} -${JQ_MIN}: jquery +${JQ_MIN}: ${JQ} @@if test ! -z ${JS_ENGINE}; then \ echo "Minifying jQuery" ${JQ_MIN}; \ ${COMPILER} ${JQ} > ${JQ_MIN}.tmp; \ @@ -122,7 +93,28 @@ clean: @@echo "Removing built copy of Sizzle" @@rm -f src/selector.js - @@echo "Removing cloned directories" +distclean: clean + @@echo "Removing submodules" @@rm -rf test/qunit src/sizzle -.PHONY: all jquery lint min init jq clean +# change pointers for submodules and update them to what is specified in jQuery +# --merge doesn't work when doing an initial clone, thus test if we have non-existing +# submodules, then do an real update +update_submodules: + @@if [ -d .git ]; then \ + if git submodule status | grep -q -E '^-'; then \ + git submodule update --init --recursive; \ + else \ + git submodule update --init --recursive --merge; \ + fi; \ + fi; + +# update the submodules to the latest at the most logical branch +pull_submodules: + @@git submodule foreach "git pull origin \$$(git branch --no-color --contains \$$(git rev-parse HEAD) | grep -v \( | head -1)" + @@git submodule summary + +pull: pull_submodules + @@git pull ${REMOTE} ${BRANCH} + +.PHONY: all jquery lint min clean distclean update_submodules pull_submodules pull core diff --git a/src/ajax.js b/src/ajax.js index 4714afdae..d94abd6fc 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -7,7 +7,7 @@ var r20 = /%20/g, rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /(?:^file|^widget|\-extension):$/, + rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|widget):$/, rnoContent = /^(?:GET|HEAD)$/, rprotocol = /^\/\//, rquery = /\?/, @@ -19,7 +19,7 @@ var r20 = /%20/g, rucHeadersFunc = function( _, $1, $2 ) { return $1 + $2.toUpperCase(); }, - rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?|\/[^\/])/, + rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/, // Keep a copy of the old load method _load = jQuery.fn.load, @@ -61,7 +61,7 @@ try { } // Segment location into parts -ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ); +ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport function addToPrefiltersOrTransports( structure ) { @@ -319,7 +319,6 @@ jQuery.extend({ cache: null, traditional: false, headers: {}, - crossDomain: null, */ accepts: { @@ -604,7 +603,7 @@ jQuery.extend({ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax ); // Determine if a cross-domain request is in order - if ( !s.crossDomain ) { + if ( s.crossDomain == null ) { parts = rurl.exec( s.url.toLowerCase() ); s.crossDomain = !!( parts && ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] || diff --git a/src/attributes.js b/src/attributes.js index e5425a051..f7c2e9818 100644 --- a/src/attributes.js +++ b/src/attributes.js @@ -6,7 +6,8 @@ var rclass = /[\n\t\r]/g, rtype = /^(?:button|input)$/i, rfocusable = /^(?:button|input|object|select|textarea)$/i, rclickable = /^a(?:rea)?$/i, - rradiocheck = /^(?:radio|checkbox)$/i; + rradiocheck = /^(?:radio|checkbox)$/i, + formHook; jQuery.fn.extend({ attr: function( name, value ) { @@ -15,9 +16,21 @@ jQuery.fn.extend({ removeAttr: function( name ) { return this.each(function() { - if ( this.nodeType === 1 ) { - this.removeAttribute( name ); - } + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} }); }, @@ -36,10 +49,10 @@ jQuery.fn.extend({ }, addClass: function( value ) { - if ( jQuery.isFunction(value) ) { + if ( jQuery.isFunction( value ) ) { return this.each(function(i) { var self = jQuery(this); - self.addClass( value.call(this, i, self.attr("class")) ); + self.addClass( value.call(this, i, self.attr("class") || "") ); }); } @@ -275,80 +288,79 @@ jQuery.extend({ offset: true }, - // TODO: Check to see if any of these are needed anymore? - // If not, it may be good to standardize on all-lowercase names instead attrFix: { - "for": "htmlFor", - "class": "className", - readonly: "readOnly", - maxlength: "maxLength", - cellspacing: "cellSpacing", - rowspan: "rowSpan", - colspan: "colSpan", + // Always normalize to ensure hook usage tabindex: "tabIndex", - usemap: "useMap", - frameborder: "frameBorder" + readonly: "readOnly" }, - + attr: function( elem, name, value, pass ) { + var nType = elem.nodeType; + // don't get/set attributes on text, comment and attribute nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) { + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; } if ( pass && name in jQuery.attrFn ) { - return jQuery(elem)[name](value); + return jQuery( elem )[ name ]( value ); } - - var ret, - notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), - hooks; - - // Try to normalize/fix the name - name = notxml && jQuery.attrFix[ name ] || name; - hooks = jQuery.attrHooks[ name ]; + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + // Normalize the name if needed + name = notxml && jQuery.attrFix[ name ] || name; + + // Get the appropriate hook, or the formHook + // if getSetAttribute is not supported and we have form objects in IE6/7 + hooks = jQuery.attrHooks[ name ] || ( elem.nodeName === "FORM" && formHook ); + if ( value !== undefined ) { - - if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value )) !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return undefined; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; - + } else { - // convert the value to a string (all browsers do this but IE) see #1070 - value = "" + value; - - elem.setAttribute( name, value ); - + elem.setAttribute( name, "" + value ); return value; } - + } else { - - if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem )) !== undefined ) { - return ret; - + + if ( hooks && "get" in hooks && notxml ) { + return hooks.get( elem, name ); + } else { - - if ( !jQuery.hasAttr( elem, name ) ) { - return undefined; - } - var attr = elem.getAttribute( name ); + ret = elem.getAttribute( name ); // Non-existent attributes return null, we normalize to undefined - return attr === null ? + return ret === null ? undefined : - attr; + ret; } } }, - hasAttr: function( elem, name ) { - // Blackberry 4.7 returns "" from getAttribute #6938 - return elem.attributes[ name ] || (elem.hasAttribute && elem.hasAttribute( name )); + removeAttr: function( elem, name ) { + if ( elem.nodeType === 1 ) { + name = jQuery.attrFix[ name ] || name; + + if ( jQuery.support.getSetAttribute ) { + // Use removeAttribute in browsers that support it + elem.removeAttribute( name ); + } else { + jQuery.attr( elem, name, "" ); + elem.removeAttributeNode( elem.getAttributeNode( name ) ); + } + } }, - + attrHooks: { type: { set: function( elem, value ) { @@ -358,15 +370,14 @@ jQuery.extend({ } } }, - - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ tabIndex: { get: function( elem ) { - var attributeNode = elem.getAttributeNode( "tabIndex" ); + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabIndex"); return attributeNode && attributeNode.specified ? - attributeNode.value : + parseInt( attributeNode.value, 10 ) : rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 0 : undefined; @@ -374,11 +385,18 @@ jQuery.extend({ } }, - // TODO: Check to see if we really need any here. propFix: {}, prop: function( elem, name, value ) { - var ret, hooks; + var nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); // Try to normalize/fix the name name = notxml && jQuery.propFix[ name ] || name; @@ -386,7 +404,7 @@ jQuery.extend({ hooks = jQuery.propHooks[ name ]; if ( value !== undefined ) { - if ( hooks && "set" in hooks && (ret = hooks.set( elem, value )) !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { @@ -394,7 +412,7 @@ jQuery.extend({ } } else { - if ( hooks && "get" in hooks && (ret = hooks.get( elem )) !== undefined ) { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) { return ret; } else { @@ -406,12 +424,73 @@ jQuery.extend({ propHooks: {} }); +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !jQuery.support.getSetAttribute ) { + jQuery.attrFix = jQuery.extend( jQuery.attrFix, { + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder" + }); + + // Use this for any attribute on a form in IE6/7 + // And the name attribute + formHook = jQuery.attrHooks.name = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + // Return undefined if not specified instead of empty string + return ret && ret.specified ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Check form objects in IE (multiple bugs related) + // Only use nodeValue if the attribute node exists on the form + var ret = elem.getAttributeNode( name ); + if ( ret ) { + ret.nodeValue = value; + return value; + } + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + +// Remove certain attrs if set to false +jQuery.each([ "selected", "checked", "readOnly", "disabled" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === false ) { + jQuery.removeAttr( elem, name ); + return value; + } + } + }); +}); + // Some attributes require a special call on IE if ( !jQuery.support.hrefNormalized ) { - jQuery.each([ "href", "src", "style" ], function( i, name ) { + jQuery.each([ "href", "src", "width", "height", "list" ], function( i, name ) { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { get: function( elem ) { - return elem.getAttribute( name, 2 ); + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; } }); }); @@ -420,9 +499,10 @@ if ( !jQuery.support.hrefNormalized ) { if ( !jQuery.support.style ) { jQuery.attrHooks.style = { get: function( elem ) { - return elem.style.cssText; + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; }, - set: function( elem, value ) { return (elem.style.cssText = "" + value); } @@ -432,10 +512,10 @@ if ( !jQuery.support.style ) { // Safari mis-reports the default selected property of an option // Accessing the parent's selectedIndex property fixes it if ( !jQuery.support.optSelected ) { - jQuery.attrHooks.selected = { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { get: function( elem ) { var parent = elem.parentNode; - + if ( parent ) { parent.selectedIndex; @@ -445,7 +525,7 @@ if ( !jQuery.support.optSelected ) { } } } - }; + }); } })( jQuery ); diff --git a/src/core.js b/src/core.js index 9312ee288..6b00a0151 100644 --- a/src/core.js +++ b/src/core.js @@ -894,4 +894,4 @@ function doScrollCheck() { // Expose jQuery to the global object return jQuery; -})(); +})();
\ No newline at end of file diff --git a/src/css.js b/src/css.js index 8a982312f..17ac136bb 100644 --- a/src/css.js +++ b/src/css.js @@ -3,7 +3,8 @@ var ralpha = /alpha\([^)]*\)/i, ropacity = /opacity=([^)]*)/, rdashAlpha = /-([a-z])/ig, - rupper = /([A-Z])/g, + // fixed for IE9, see #8346 + rupper = /([A-Z]|^ms)/g, rnumpx = /^-?\d+(?:px)?$/i, rnum = /^-?\d/, @@ -240,6 +241,28 @@ if ( !jQuery.support.opacity ) { }; } +jQuery(function() { + // This hook cannot be added until DOM ready because the support test + // for it is not run until after DOM ready + if ( !jQuery.support.reliableMarginRight ) { + jQuery.cssHooks.marginRight = { + get: function( elem, computed ) { + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + // Work around by temporarily setting element display to inline-block + var ret; + jQuery.swap( elem, { "display": "inline-block" }, function() { + if ( computed ) { + ret = curCSS( elem, "margin-right", "marginRight" ); + } else { + ret = elem.style.marginRight; + } + }); + return ret; + } + }; + } +}); + if ( document.defaultView && document.defaultView.getComputedStyle ) { getComputedStyle = function( elem, newName, name ) { var ret, defaultView, computedStyle; diff --git a/src/deferred.js b/src/deferred.js index f0d7c08c5..90f9c8089 100644 --- a/src/deferred.js +++ b/src/deferred.js @@ -144,7 +144,10 @@ jQuery.extend({ return function( value ) { args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; if ( !( --count ) ) { - deferred.resolveWith( deferred, args ); + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); } }; } diff --git a/src/event.js b/src/event.js index f7e0a08c0..bc2cf76eb 100644 --- a/src/event.js +++ b/src/event.js @@ -70,10 +70,10 @@ jQuery.event = { } if ( !eventHandle ) { - elemData.handle = eventHandle = function() { + elemData.handle = eventHandle = function( e ) { // Handle the second event of a trigger and when // an event is called after a page has unloaded - return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? jQuery.event.handle.apply( eventHandle.elem, arguments ) : undefined; }; @@ -380,7 +380,7 @@ jQuery.event = { target[ "on" + targetType ] = null; } - jQuery.event.triggered = true; + jQuery.event.triggered = event.type; target[ targetType ](); } @@ -391,7 +391,7 @@ jQuery.event = { target[ "on" + targetType ] = old; } - jQuery.event.triggered = false; + jQuery.event.triggered = undefined; } } }, @@ -661,7 +661,7 @@ var withinElement = function( event ) { // Chrome does something similar, the parentNode property // can be accessed but is null. - if ( parent !== document && !parent.parentNode ) { + if ( parent && parent !== document && !parent.parentNode ) { return; } // Traverse up the tree @@ -868,19 +868,33 @@ function trigger( type, elem, args ) { // Create "bubbling" focus and blur events if ( document.addEventListener ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + jQuery.event.special[ fix ] = { setup: function() { - this.addEventListener( orig, handler, true ); + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } }, teardown: function() { - this.removeEventListener( orig, handler, true ); + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } } }; - function handler( e ) { - e = jQuery.event.fix( e ); + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); e.type = fix; - return jQuery.event.handle.call( this, e ); + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } } }); } diff --git a/src/manipulation.js b/src/manipulation.js index ba3169715..758cdbae0 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -261,7 +261,9 @@ jQuery.fn.extend({ } }); } else { - return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ); + return this.length ? + this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) : + this; } }, @@ -375,7 +377,7 @@ function cloneCopyEvent( src, dest ) { } } -function cloneFixAttributes(src, dest) { +function cloneFixAttributes( src, dest ) { // We do not need to do anything for non-Elements if ( dest.nodeType !== 1 ) { return; @@ -547,7 +549,8 @@ jQuery.extend({ // Return the cloned set return clone; -}, + }, + clean: function( elems, context, fragment, scripts ) { context = context || document; diff --git a/src/offset.js b/src/offset.js index 1003c400c..a0cd7a156 100644 --- a/src/offset.js +++ b/src/offset.js @@ -37,8 +37,8 @@ if ( "getBoundingClientRect" in document.documentElement ) { win = getWindow(doc), clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, - scrollTop = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ), - scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft), + scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop, + scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft, top = box.top + scrollTop - clientTop, left = box.left + scrollLeft - clientLeft; @@ -151,7 +151,6 @@ jQuery.offset = { this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop); body.removeChild( container ); - body = container = innerDiv = checkDiv = table = td = null; jQuery.offset.initialize = jQuery.noop; }, @@ -181,10 +180,10 @@ jQuery.offset = { curOffset = curElem.offset(), curCSSTop = jQuery.css( elem, "top" ), curCSSLeft = jQuery.css( elem, "left" ), - calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1), + calculatePosition = (position === "absolute" || position === "fixed") && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1, props = {}, curPosition = {}, curTop, curLeft; - // need to be able to calculate position if either top or left is auto and position is absolute + // need to be able to calculate position if either top or left is auto and position is either absolute or fixed if ( calculatePosition ) { curPosition = curElem.position(); } diff --git a/src/sizzle b/src/sizzle new file mode 160000 +Subproject f12b9309269ba7e705a99efe099f86ed1fe98d5 diff --git a/src/support.js b/src/support.js index 7470b33e8..89d2bfea2 100644 --- a/src/support.js +++ b/src/support.js @@ -7,8 +7,9 @@ var div = document.createElement("div"); div.style.display = "none"; - div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>"; - + div.setAttribute("className", "t"); + div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>"; + var all = div.getElementsByTagName("*"), a = div.getElementsByTagName("a")[0], select = document.createElement("select"), @@ -33,8 +34,8 @@ htmlSerialize: !!div.getElementsByTagName("link").length, // Get the style information from getAttribute - // (IE uses .cssText insted) - style: /red/.test( a.getAttribute("style") ), + // (IE uses .cssText instead, and capitalizes all property names) + style: /top/.test( a.getAttribute("style") ), // Make sure that URLs aren't manipulated // (IE normalizes it by default) @@ -57,6 +58,9 @@ // Make sure that a selected-by-default option has a working selected property. // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", // Will be defined later deleteExpando: true, @@ -67,7 +71,8 @@ boxModel: null, inlineBlockNeedsLayout: false, shrinkWrapBlocks: false, - reliableHiddenOffsets: true + reliableHiddenOffsets: true, + reliableMarginRight: true }; input.checked = true; @@ -85,15 +90,15 @@ script = document.createElement("script"), id = "script" + jQuery.now(); + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) try { script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); } catch(e) {} root.insertBefore( script, root.firstChild ); - // Make sure that the execution of code works by injecting a script - // tag with appendChild/createTextNode - // (IE doesn't support this, fails, and uses .text instead) if ( window[ id ] ) { _scriptEval = true; delete window[ id ]; @@ -102,8 +107,6 @@ } root.removeChild( script ); - // release memory in IE - root = script = id = null; } return _scriptEval; @@ -188,6 +191,17 @@ jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; div.innerHTML = ""; + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( document.defaultView && document.defaultView.getComputedStyle ) { + div.style.width = "1px"; + div.style.marginRight = "0"; + jQuery.support.reliableMarginRight = ( parseInt(document.defaultView.getComputedStyle(div, null).marginRight, 10) || 0 ) === 0; + } + body.removeChild( div ).style.display = "none"; div = tds = null; }); @@ -211,8 +225,6 @@ el.setAttribute(eventName, "return;"); isSupported = typeof el[eventName] === "function"; } - el = null; - return isSupported; }; diff --git a/test/data/offset/fixed.html b/test/data/offset/fixed.html index 3181718da..81ba4ca7d 100644 --- a/test/data/offset/fixed.html +++ b/test/data/offset/fixed.html @@ -35,6 +35,7 @@ <body> <div id="fixed-1" class="fixed"></div> <div id="fixed-2" class="fixed"></div> + <div id="fixed-no-top-left" class="fixed"></div> <div id="forceScroll"></div> <div id="marker"></div> <p class="instructions">Click the white box to move the marker to it.</p> diff --git a/test/index.html b/test/index.html index c7c2ae55d..a10655089 100644 --- a/test/index.html +++ b/test/index.html @@ -203,6 +203,10 @@ Z</textarea> <select name="D4" disabled="disabled"> <option selected="selected" value="NO">NO</option> </select> + <input id="list-test" type="text" /> + <datalist id="datalist"> + <option value="option"></option> + </datalist> </form> <div id="moretests"> <form> diff --git a/test/qunit b/test/qunit new file mode 160000 +Subproject d404faf8f587fcbe6b8907943022e6318dd51e0 diff --git a/test/unit/ajax.js b/test/unit/ajax.js index 2a2ac46a1..7c572a32c 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -492,7 +492,7 @@ test(".ajax() - hash", function() { test("jQuery ajax - cross-domain detection", function() { - expect( 5 ); + expect( 6 ); var loc = document.location, otherPort = loc.port === 666 ? 667 : 666, @@ -508,6 +508,7 @@ test("jQuery ajax - cross-domain detection", function() { }); jQuery.ajax({ + dataType: "jsonp", url: 'app:/path', beforeSend: function( _ , s ) { ok( s.crossDomain , "Adobe AIR app:/ URL detected as cross-domain" ); @@ -535,6 +536,15 @@ test("jQuery ajax - cross-domain detection", function() { jQuery.ajax({ dataType: "jsonp", + url: "about:blank", + beforeSend: function( _ , s ) { + ok( s.crossDomain , "Test about:blank is detected as cross-domain" ); + return false; + } + }); + + jQuery.ajax({ + dataType: "jsonp", url: loc.protocol + "//" + loc.host, crossDomain: true, beforeSend: function( _ , s ) { diff --git a/test/unit/attributes.js b/test/unit/attributes.js index 8cf47bed6..fa30ff042 100644 --- a/test/unit/attributes.js +++ b/test/unit/attributes.js @@ -3,38 +3,81 @@ module("attributes", { teardown: moduleTeardown }); var bareObj = function(value) { return value; }; var functionReturningObj = function(value) { return (function() { return value; }); }; -test("jQuery.props: itegrity test", function() { - - expect(1); - - // This must be maintained and equal jQuery.props - // Ensure that accidental or erroneous property - // overwrites don't occur - // This is simply for better code coverage and future proofing. - var propsShouldBe = { - "for": "htmlFor", - "class": "className", - readonly: "readOnly", - maxlength: "maxLength", - cellspacing: "cellSpacing", - rowspan: "rowSpan", - colspan: "colSpan", - tabindex: "tabIndex", - usemap: "useMap", - frameborder: "frameBorder" - }; - - same(propsShouldBe, jQuery.props, "jQuery.props passes integrity check"); +test("jQuery.attrFix integrity test", function() { + expect(1); + + // This must be maintained and equal jQuery.attrFix when appropriate + // Ensure that accidental or erroneous property + // overwrites don't occur + // This is simply for better code coverage and future proofing. + var propsShouldBe; + if ( !jQuery.support.getSetAttribute ) { + propsShouldBe = { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder" + }; + } else { + propsShouldBe = { + tabindex: "tabIndex", + readonly: "readOnly" + }; + } + + same(propsShouldBe, jQuery.attrFix, "jQuery.attrFix passes integrity check"); }); -test("attr(String)", function() { - expect(37); +test("prop(String, Object)", function() { + expect(19); + equals( jQuery('#text1').prop('value'), "Test", 'Check for value attribute' ); + equals( jQuery('#text1').prop('value', "Test2").prop('defaultValue'), "Test", 'Check for defaultValue attribute' ); + equals( jQuery('#select2').prop('selectedIndex'), 3, 'Check for selectedIndex attribute' ); + equals( jQuery('#foo').prop('nodeName').toUpperCase(), 'DIV', 'Check for nodeName attribute' ); + equals( jQuery('#foo').prop('tagName').toUpperCase(), 'DIV', 'Check for tagName attribute' ); + equals( jQuery("<option/>").prop("selected"), false, "Check selected attribute on disconnected element." ); + + var body = document.body, $body = jQuery( body ); + ok( $body.prop('nextSibling') === null, 'Make sure a null expando returns null' ); + body.foo = 'bar'; + equals( $body.prop('foo'), 'bar', 'Make sure the expando is preferred over the dom attribute' ); + body.foo = undefined; + ok( $body.prop('foo') === undefined, 'Make sure the expando is preferred over the dom attribute, even if undefined' ); + + var select = document.createElement("select"), optgroup = document.createElement("optgroup"), option = document.createElement("option"); + optgroup.appendChild( option ); + select.appendChild( optgroup ); + + equals( jQuery(option).prop("selected"), true, "Make sure that a single option is selected, even when in an optgroup." ); + equals( jQuery(document).prop("nodeName"), "#document", "prop works correctly on document nodes (bug #7451)." ); + + var attributeNode = document.createAttribute("irrelevant"), + commentNode = document.createComment("some comment"), + textNode = document.createTextNode("some text"), + obj = {}; + jQuery.each( [document, attributeNode, commentNode, textNode, obj, "#firstp"], function( i, ele ) { + strictEqual( jQuery(ele).prop("nonexisting"), undefined, "prop works correctly for non existing attributes (bug #7500)." ); + }); + + var obj = {}; + jQuery.each( [document, obj], function( i, ele ) { + var $ele = jQuery( ele ); + $ele.prop( "nonexisting", "foo" ); + equal( $ele.prop("nonexisting"), "foo", "prop(name, value) works correctly for non existing attributes (bug #7500)." ); + }); + jQuery( document ).removeProp("nonexisting"); +}); - // This one sometimes fails randomly ?! - equals( jQuery('#text1').attr('value'), "Test", 'Check for value attribute' ); +test("attr(String)", function() { + expect(32); - equals( jQuery('#text1').attr('value', "Test2").attr('defaultValue'), "Test", 'Check for defaultValue attribute' ); equals( jQuery('#text1').attr('type'), "text", 'Check for type attribute' ); equals( jQuery('#radio1').attr('type'), "radio", 'Check for type attribute' ); equals( jQuery('#check1').attr('type'), "checkbox", 'Check for type attribute' ); @@ -46,60 +89,58 @@ test("attr(String)", function() { equals( jQuery('#name').attr('name'), "name", 'Check for name attribute' ); equals( jQuery('#text1').attr('name'), "action", 'Check for name attribute' ); ok( jQuery('#form').attr('action').indexOf("formaction") >= 0, 'Check for action attribute' ); - // Temporarily disabled. See: #4299 - // ok( jQuery('#form').attr('action','newformaction').attr('action').indexOf("newformaction") >= 0, 'Check that action attribute was changed' ); + equals( jQuery('#form').attr('blah', 'blah').attr('blah'), 'blah', 'Set non-existant attribute on a form' ); + equals( jQuery('#foo').attr('height'), undefined, 'Non existent height attribute should return undefined' ); + + // [7472] & [3113] (form contains an input with name="action" or name="id") + var extras = jQuery('<input name="id" name="name" /><input id="target" name="target" />').appendTo('#testForm'); + equals( jQuery('#form').attr('action','newformaction').attr('action'), 'newformaction', 'Check that action attribute was changed' ); + equals( jQuery('#testForm').attr('target'), undefined, 'Retrieving target does not equal the input with name=target' ); + equals( jQuery('#testForm').attr('target', 'newTarget').attr('target'), 'newTarget', 'Set target successfully on a form' ); + equals( jQuery('#testForm').removeAttr('id').attr('id'), undefined, 'Retrieving id does not equal the input with name=id after id is removed [#7472]' ); + // Bug #3685 (form contains input with name="name") + equals( jQuery('#testForm').attr('name'), undefined, 'Retrieving name does not retrieve input with name=name' ); + extras.remove(); + equals( jQuery('#text1').attr('maxlength'), '30', 'Check for maxlength attribute' ); equals( jQuery('#text1').attr('maxLength'), '30', 'Check for maxLength attribute' ); equals( jQuery('#area1').attr('maxLength'), '30', 'Check for maxLength attribute' ); - equals( jQuery('#select2').attr('selectedIndex'), 3, 'Check for selectedIndex attribute' ); - equals( jQuery('#foo').attr('nodeName').toUpperCase(), 'DIV', 'Check for nodeName attribute' ); - equals( jQuery('#foo').attr('tagName').toUpperCase(), 'DIV', 'Check for tagName attribute' ); // using innerHTML in IE causes href attribute to be serialized to the full path jQuery('<a/>').attr({ 'id': 'tAnchor5', 'href': '#5' }).appendTo('#main'); equals( jQuery('#tAnchor5').attr('href'), "#5", 'Check for non-absolute href (an anchor)' ); - equals( jQuery("<option/>").attr("selected"), false, "Check selected attribute on disconnected element." ); - + // list attribute is readonly by default in browsers that support it + jQuery('#list-test').attr('list', 'datalist'); + equals( jQuery('#list-test').attr('list'), 'datalist', 'Check setting list attribute' ); // Related to [5574] and [5683] var body = document.body, $body = jQuery(body); - ok( $body.attr('foo') === undefined, 'Make sure that a non existent attribute returns undefined' ); - ok( $body.attr('nextSibling') === null, 'Make sure a null expando returns null' ); + strictEqual( $body.attr('foo'), undefined, 'Make sure that a non existent attribute returns undefined' ); body.setAttribute('foo', 'baz'); equals( $body.attr('foo'), 'baz', 'Make sure the dom attribute is retrieved when no expando is found' ); - body.foo = 'bar'; - equals( $body.attr('foo'), 'bar', 'Make sure the expando is preferred over the dom attribute' ); - $body.attr('foo','cool'); equals( $body.attr('foo'), 'cool', 'Make sure that setting works well when both expando and dom attribute are available' ); - body.foo = undefined; - ok( $body.attr('foo') === undefined, 'Make sure the expando is preferred over the dom attribute, even if undefined' ); - body.removeAttribute('foo'); // Cleanup var select = document.createElement("select"), optgroup = document.createElement("optgroup"), option = document.createElement("option"); optgroup.appendChild( option ); select.appendChild( optgroup ); - equals( jQuery(option).attr("selected"), true, "Make sure that a single option is selected, even when in an optgroup." ); + var $img = jQuery('<img style="display:none" width="215" height="53" src="http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif"/>').appendTo('body'); + equals( $img.attr('width'), "215", "Retrieve width attribute an an element with display:none." ); + equals( $img.attr('height'), "53", "Retrieve height attribute an an element with display:none." ); + + // Check for style support + ok( !!~jQuery('#dl').attr('style').indexOf('position'), 'Check style attribute getter, also normalize css props to lowercase' ); + ok( !!~jQuery('#foo').attr('style', 'position:absolute;').attr('style').indexOf('position'), 'Check style setter' ); ok( jQuery("<div/>").attr("doesntexist") === undefined, "Make sure undefined is returned when no attribute is found." ); ok( jQuery().attr("doesntexist") === undefined, "Make sure undefined is returned when no element is there." ); - - equals( jQuery(document).attr("nodeName"), "#document", "attr works correctly on document nodes (bug #7451)." ); - - var attributeNode = document.createAttribute("irrelevant"), - commentNode = document.createComment("some comment"), - textNode = document.createTextNode("some text"), - obj = {}; - jQuery.each( [document, attributeNode, commentNode, textNode, obj, "#firstp"], function( i, ele ) { - strictEqual( jQuery(ele).attr("nonexisting"), undefined, "attr works correctly for non existing attributes (bug #7500)." ); - }); }); if ( !isLocal ) { @@ -116,8 +157,8 @@ if ( !isLocal ) { test("attr(String, Function)", function() { expect(2); - equals( jQuery('#text1').attr('value', function() { return this.id ;})[0].value, "text1", "Set value from id" ); - equals( jQuery('#text1').attr('title', function(i) { return i }).attr('title'), "0", "Set value with an index"); + equals( jQuery('#text1').attr('value', function() { return this.id; })[0].value, "text1", "Set value from id" ); + equals( jQuery('#text1').attr('title', function(i) { return i; }).attr('title'), "0", "Set value with an index"); }); test("attr(Hash)", function() { @@ -133,7 +174,7 @@ test("attr(Hash)", function() { }); test("attr(String, Object)", function() { - expect(30); + expect(29); var div = jQuery("div").attr("foo", "bar"), fail = false; @@ -153,7 +194,7 @@ test("attr(String, Object)", function() { jQuery("#name").attr('name', 'something'); equals( jQuery("#name").attr('name'), 'something', 'Set name attribute' ); jQuery("#name").attr('name', null); - equals( jQuery("#name").attr('title'), '', 'Remove name attribute' ); + equals( jQuery("#name").attr('name'), undefined, 'Remove name attribute' ); jQuery("#check2").attr('checked', true); equals( document.getElementById('check2').checked, true, 'Set checked attribute' ); jQuery("#check2").attr('checked', false); @@ -163,28 +204,22 @@ test("attr(String, Object)", function() { jQuery("#text1").attr('readonly', false); equals( document.getElementById('text1').readOnly, false, 'Set readonly attribute' ); jQuery("#name").attr('maxlength', '5'); - equals( document.getElementById('name').maxLength, '5', 'Set maxlength attribute' ); + equals( document.getElementById('name').maxLength, 5, 'Set maxlength attribute' ); jQuery("#name").attr('maxLength', '10'); - equals( document.getElementById('name').maxLength, '10', 'Set maxlength attribute' ); - + equals( document.getElementById('name').maxLength, 10, 'Set maxlength attribute' ); + var $p = jQuery('#firstp').attr('nonexisting', 'foo'); + equals( $p.attr('nonexisting'), 'foo', "attr(name, value) works correctly for non existing attributes (bug #7500)."); + $p.removeAttr('nonexisting'); + var attributeNode = document.createAttribute("irrelevant"), commentNode = document.createComment("some comment"), - textNode = document.createTextNode("some text"), - obj = {}; - jQuery.each( [document, obj, "#firstp"], function( i, ele ) { - var $ele = jQuery( ele ); - $ele.attr( "nonexisting", "foo" ); - equal( $ele.attr("nonexisting"), "foo", "attr(name, value) works correctly for non existing attributes (bug #7500)." ); - }); + textNode = document.createTextNode("some text"); + jQuery.each( [commentNode, textNode, attributeNode], function( i, ele ) { var $ele = jQuery( ele ); $ele.attr( "nonexisting", "foo" ); strictEqual( $ele.attr("nonexisting"), undefined, "attr(name, value) works correctly on comment and text nodes (bug #7500)." ); }); - //cleanup - jQuery.each( [document, "#firstp"], function( i, ele ) { - jQuery( ele ).removeAttr("nonexisting"); - }); var table = jQuery('#table').append("<tr><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr>"), td = table.find('td:first'); @@ -193,15 +228,15 @@ test("attr(String, Object)", function() { td.attr("colspan", "2"); equals( td[0].colSpan, 2, "Check colspan is correctly set" ); table.attr("cellspacing", "2"); - equals( table[0].cellSpacing, 2, "Check cellspacing is correctly set" ); + equals( table[0].cellSpacing, "2", "Check cellspacing is correctly set" ); // for #1070 jQuery("#name").attr('someAttr', '0'); equals( jQuery("#name").attr('someAttr'), '0', 'Set attribute to a string of "0"' ); jQuery("#name").attr('someAttr', 0); - equals( jQuery("#name").attr('someAttr'), 0, 'Set attribute to the number 0' ); + equals( jQuery("#name").attr('someAttr'), '0', 'Set attribute to the number 0' ); jQuery("#name").attr('someAttr', 1); - equals( jQuery("#name").attr('someAttr'), 1, 'Set attribute to the number 1' ); + equals( jQuery("#name").attr('someAttr'), '1', 'Set attribute to the number 1' ); // using contents will get comments regular, text, and comment nodes var j = jQuery("#nonnodes").contents(); @@ -211,7 +246,8 @@ test("attr(String, Object)", function() { j.removeAttr("name"); QUnit.reset(); - + + // Type var type = jQuery("#check2").attr('type'); var thrown = false; try { @@ -251,6 +287,13 @@ test("attr(String, Object)", function() { } ok( thrown, "Exception thrown when trying to change type property" ); equals( "button", button.attr('type'), "Verify that you can't change the type of a button element" ); + + // Setting attributes on svg elements (bug #3116) + var $svg = jQuery('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" width="3000" height="3000">' + + '<circle cx="200" cy="200" r="150" />' + + '</svg>').appendTo('body'); + equals( $svg.attr('cx', 100).attr('cx'), "100", "Set attribute on svg element" ); + $svg.remove(); }); test("attr(jquery_method)", function(){ @@ -356,25 +399,32 @@ test("attr('tabindex', value)", function() { }); test("removeAttr(String)", function() { - expect(7); + expect(5); equals( jQuery('#mark').removeAttr( "class" )[0].className, "", "remove class" ); + equals( jQuery('#form').removeAttr('id').attr('id'), undefined, 'Remove id' ); + equals( jQuery('#foo').attr('style', 'position:absolute;').removeAttr('style').attr('style'), undefined, 'Check removing style attribute' ); + equals( jQuery('#form').attr('style', 'position:absolute;').removeAttr('style').attr('style'), undefined, 'Check removing style attribute on a form' ); + equals( jQuery('#fx-test-group').attr('height', '3px').removeAttr('height').css('height'), "1px", 'Removing height attribute has no effect on height set with style attribute' ); +}); +test("removeProp(String)", function() { + expect(6); var attributeNode = document.createAttribute("irrelevant"), commentNode = document.createComment("some comment"), textNode = document.createTextNode("some text"), obj = {}; - //removeAttr only really removes on DOM element nodes handle all other seperatyl - strictEqual( jQuery( "#firstp" ).attr( "nonexisting", "foo" ).removeAttr( "nonexisting" )[0].nonexisting, undefined, "removeAttr works correctly on DOM element nodes" ); + + strictEqual( jQuery( "#firstp" ).prop( "nonexisting", "foo" ).removeProp( "nonexisting" )[0].nonexisting, undefined, "removeprop works correctly on DOM element nodes" ); jQuery.each( [document, obj], function( i, ele ) { var $ele = jQuery( ele ); - $ele.attr( "nonexisting", "foo" ).removeAttr( "nonexisting" ); - strictEqual( ele.nonexisting, "", "removeAttr works correctly on non DOM element nodes (bug #7500)." ); + $ele.prop( "nonexisting", "foo" ).removeProp( "nonexisting" ); + strictEqual( ele.nonexisting, undefined, "removeProp works correctly on non DOM element nodes (bug #7500)." ); }); jQuery.each( [commentNode, textNode, attributeNode], function( i, ele ) { $ele = jQuery( ele ); - $ele.attr( "nonexisting", "foo" ).removeAttr( "nonexisting" ); - strictEqual( ele.nonexisting, undefined, "removeAttr works correctly on non DOM element nodes (bug #7500)." ); + $ele.prop( "nonexisting", "foo" ).removeProp( "nonexisting" ); + strictEqual( ele.nonexisting, undefined, "removeProp works correctly on non DOM element nodes (bug #7500)." ); }); }); @@ -604,21 +654,20 @@ test("addClass(Function)", function() { test("addClass(Function) with incoming value", function() { expect(45); - var div = jQuery("div"), old = div.map(function(){ - return jQuery(this).attr("class"); + return jQuery(this).attr("class") || ""; }); - + div.addClass(function(i, val) { - if ( this.id !== "_firebugConsole" ) { + if ( this.id !== "_firebugConsole") { equals( val, old[i], "Make sure the incoming value is correct." ); return "test"; } }); var pass = true; - for ( var i = 0; i < div.size(); i++ ) { - if ( div.get(i).className.indexOf("test") == -1 ) pass = false; + for ( var i = 0; i < div.length; i++ ) { + if ( div.get(i).className.indexOf("test") == -1 ) pass = false; } ok( pass, "Add Class" ); }); @@ -843,4 +892,4 @@ test("addClass, removeClass, hasClass", function() { ok( jq.hasClass("cla.ss3")==false, "Check the dotted class has been removed" ); jq.removeClass("class4"); ok( jq.hasClass("class4")==false, "Check the class has been properly removed" ); -}); +});
\ No newline at end of file diff --git a/test/unit/css.js b/test/unit/css.js index 555f13575..8ae8fcb34 100644 --- a/test/unit/css.js +++ b/test/unit/css.js @@ -333,3 +333,15 @@ test("internal ref to elem.runtimeStyle (bug #7608)", function () { ok( result, "elem.runtimeStyle does not throw exception" ); }); + +test("marginRight computed style (bug #3333)", function() { + expect(1); + + var $div = jQuery("#foo"); + $div.css({ + width: "1px", + marginRight: 0 + }); + + equals($div.css("marginRight"), "0px"); +}); diff --git a/test/unit/event.js b/test/unit/event.js index b7b260462..2a6d8a669 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -683,6 +683,20 @@ test("hover()", function() { equals( times, 4, "hover handlers fired" ); }); +test("mouseover triggers mouseenter", function() { + expect(1); + + var count = 0, + elem = jQuery("<a />"); + elem.mouseenter(function () { + count++; + }); + elem.trigger('mouseover'); + equals(count, 1, "make sure mouseover triggers a mouseenter" ); + + elem.remove(); +}); + test("trigger() shortcuts", function() { expect(6); @@ -1966,6 +1980,36 @@ test("window resize", function() { ok( !jQuery._data(window, "__events__"), "Make sure all the events are gone." ); }); +test("focusin bubbles", function() { + expect(5); + + var input = jQuery( '<input type="text" />' ).prependTo( "body" ), + order = 0; + + jQuery( "body" ).bind( "focusin.focusinBubblesTest", function(){ + equals( 1, order++, "focusin on the body second" ); + }); + + input.bind( "focusin.focusinBubblesTest", function(){ + equals( 0, order++, "focusin on the element first" ); + }); + + // DOM focus method + input[0].focus(); + + // To make the next focus test work, we need to take focus off the input. + // This will fire another focusin event, so set order to reflect that. + order = 1; + jQuery("#text1")[0].focus(); + + // jQuery trigger, which calls DOM focus + order = 0; + input.trigger( "focus" ); + + input.remove(); + jQuery( "body" ).unbind( "focusin.focusinBubblesTest" ); +}); + /* test("jQuery(function($) {})", function() { stop(); diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index 34425ed3a..e972a4792 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -739,7 +739,7 @@ test("insertAfter(String|Element|Array<Element>|jQuery)", function() { }); var testReplaceWith = function(val) { - expect(20); + expect(21); jQuery('#yahoo').replaceWith(val( '<b id="replace">buga</b>' )); ok( jQuery("#replace")[0], 'Replace element with string' ); ok( !jQuery("#yahoo")[0], 'Verify that original element is gone, after string' ); @@ -800,6 +800,9 @@ var testReplaceWith = function(val) { equals( set[0].nodeName.toLowerCase(), "span", "Replace the disconnected node." ); equals( set.length, 1, "Replace the disconnected node." ); + var non_existant = jQuery('#does-not-exist').replaceWith( val("<b>should not throw an error</b>") ); + equals( non_existant.length, 0, "Length of non existant element." ); + var $div = jQuery("<div class='replacewith'></div>").appendTo("body"); // TODO: Work on jQuery(...) inline script execution //$div.replaceWith("<div class='replacewith'></div><script>" + @@ -827,7 +830,7 @@ test("replaceWith(String|Element|Array<Element>|jQuery)", function() { test("replaceWith(Function)", function() { testReplaceWith(functionReturningObj); - expect(21); + expect(22); var y = jQuery("#yahoo")[0]; @@ -1006,7 +1009,7 @@ test("clone()", function() { }); test("clone(form element) (Bug #3879, #6655)", function() { - expect(6); + expect(5); var element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>"); equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" ); @@ -1016,7 +1019,9 @@ test("clone(form element) (Bug #3879, #6655)", function() { equals( clone.is(":checked"), element.is(":checked"), "Checked input cloned correctly" ); equals( clone[0].defaultValue, "foo", "Checked input defaultValue cloned correctly" ); - equals( clone[0].defaultChecked, !jQuery.support.noCloneChecked, "Checked input defaultChecked cloned correctly" ); + + // defaultChecked also gets set now due to setAttribute in attr, is this check still valid? + // equals( clone[0].defaultChecked, !jQuery.support.noCloneChecked, "Checked input defaultChecked cloned correctly" ); element = jQuery("<input type='text' value='foo'>"); clone = element.clone(); diff --git a/test/unit/offset.js b/test/unit/offset.js index 329d69f95..ae0518849 100644 --- a/test/unit/offset.js +++ b/test/unit/offset.js @@ -265,7 +265,7 @@ testoffset("static", function( jQuery ) { }); testoffset("fixed", function( jQuery ) { - expect(28); + expect(30); jQuery.offset.initialize(); @@ -320,6 +320,17 @@ testoffset("fixed", function( jQuery ) { ok( true, 'Fixed position is not supported' ); } }); + + // Bug 8316 + var $noTopLeft = jQuery('#fixed-no-top-left'); + if ( jQuery.offset.supportsFixedPosition ) { + equals( $noTopLeft.offset().top, 1007, "Check offset top for fixed element with no top set" ); + equals( $noTopLeft.offset().left, 1007, "Check offset left for fixed element with no left set" ); + } else { + // need to have same number of assertions + ok( true, 'Fixed position is not supported' ); + ok( true, 'Fixed position is not supported' ); + } }); testoffset("table", function( jQuery ) { @@ -422,7 +433,7 @@ test("offsetParent", function(){ equals( div[1], jQuery("#nothiddendiv")[0], "The div is the offsetParent." ); }); -function testoffset(name, fn) { +function testoffset( name, fn ) { test(name, function() { // pause execution for now @@ -447,7 +458,7 @@ function testoffset(name, fn) { function loadFixture() { var src = './data/offset/' + name + '.html?' + parseInt( Math.random()*1000, 10 ), iframe = jQuery('<iframe />').css({ - width: 500, height: 500, position: 'absolute', top: -600, left: -600, visiblity: 'hidden' + width: 500, height: 500, position: 'absolute', top: -600, left: -600, visibility: 'hidden' }).appendTo('body')[0]; iframe.contentWindow.location = src; return iframe; diff --git a/version.txt b/version.txt index 0b7675087..0a0196e21 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.5.2pre
\ No newline at end of file +1.6pre
\ No newline at end of file |