Commit b92d2f0b authored by jeresig's avatar jeresig

Merge branch 'attrhooks.1.6v2' of https://github.com/timmywil/jquery into timmywil-attrhooks.1.6v2

Conflicts:
	src/attributes.js
parents d4e44144 3a1b4661
...@@ -4,7 +4,5 @@ dist ...@@ -4,7 +4,5 @@ dist
*~ *~
*.diff *.diff
*.patch *.patch
test/qunit
src/sizzle
/*.html /*.html
.DS_Store .DS_Store
[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
V ?= 0
SRC_DIR = src SRC_DIR = src
TEST_DIR = test TEST_DIR = test
BUILD_DIR = build BUILD_DIR = build
...@@ -38,48 +36,21 @@ JQ = ${DIST_DIR}/jquery.js ...@@ -38,48 +36,21 @@ JQ = ${DIST_DIR}/jquery.js
JQ_MIN = ${DIST_DIR}/jquery.min.js JQ_MIN = ${DIST_DIR}/jquery.min.js
SIZZLE_DIR = ${SRC_DIR}/sizzle SIZZLE_DIR = ${SRC_DIR}/sizzle
QUNIT_DIR = ${TEST_DIR}/qunit
JQ_VER = $(shell cat version.txt) JQ_VER = $(shell cat version.txt)
VER = sed "s/@VERSION/${JQ_VER}/" VER = sed "s/@VERSION/${JQ_VER}/"
DATE=$(shell git log -1 --pretty=format:%ad) DATE=$(shell git log -1 --pretty=format:%ad)
all: jquery min lint all: update_submodules core
core: jquery min lint
@@echo "jQuery build complete." @@echo "jQuery build complete."
${DIST_DIR}: ${DIST_DIR}:
@@mkdir -p ${DIST_DIR} @@mkdir -p ${DIST_DIR}
ifeq ($(strip $(V)),0) jquery: ${JQ}
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}
${JQ}: ${MODULES} | ${DIST_DIR} ${JQ}: ${MODULES} | ${DIST_DIR}
@@echo "Building" ${JQ} @@echo "Building" ${JQ}
...@@ -102,9 +73,9 @@ lint: jquery ...@@ -102,9 +73,9 @@ lint: jquery
echo "You must have NodeJS installed in order to test jQuery against JSLint."; \ echo "You must have NodeJS installed in order to test jQuery against JSLint."; \
fi fi
min: ${JQ_MIN} min: jquery ${JQ_MIN}
${JQ_MIN}: jquery ${JQ_MIN}: ${JQ}
@@if test ! -z ${JS_ENGINE}; then \ @@if test ! -z ${JS_ENGINE}; then \
echo "Minifying jQuery" ${JQ_MIN}; \ echo "Minifying jQuery" ${JQ_MIN}; \
${COMPILER} ${JQ} > ${JQ_MIN}.tmp; \ ${COMPILER} ${JQ} > ${JQ_MIN}.tmp; \
...@@ -122,7 +93,28 @@ clean: ...@@ -122,7 +93,28 @@ clean:
@@echo "Removing built copy of Sizzle" @@echo "Removing built copy of Sizzle"
@@rm -f src/selector.js @@rm -f src/selector.js
@@echo "Removing cloned directories" distclean: clean
@@echo "Removing submodules"
@@rm -rf test/qunit src/sizzle @@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
...@@ -7,7 +7,7 @@ var r20 = /%20/g, ...@@ -7,7 +7,7 @@ var r20 = /%20/g,
rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL 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, rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
// #7653, #8125, #8152: local protocol detection // #7653, #8125, #8152: local protocol detection
rlocalProtocol = /(?:^file|^widget|\-extension):$/, rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|widget):$/,
rnoContent = /^(?:GET|HEAD)$/, rnoContent = /^(?:GET|HEAD)$/,
rprotocol = /^\/\//, rprotocol = /^\/\//,
rquery = /\?/, rquery = /\?/,
...@@ -19,7 +19,7 @@ var r20 = /%20/g, ...@@ -19,7 +19,7 @@ var r20 = /%20/g,
rucHeadersFunc = function( _, $1, $2 ) { rucHeadersFunc = function( _, $1, $2 ) {
return $1 + $2.toUpperCase(); return $1 + $2.toUpperCase();
}, },
rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?|\/[^\/])/, rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
// Keep a copy of the old load method // Keep a copy of the old load method
_load = jQuery.fn.load, _load = jQuery.fn.load,
...@@ -61,7 +61,7 @@ try { ...@@ -61,7 +61,7 @@ try {
} }
// Segment location into parts // Segment location into parts
ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ); ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) { function addToPrefiltersOrTransports( structure ) {
...@@ -319,7 +319,6 @@ jQuery.extend({ ...@@ -319,7 +319,6 @@ jQuery.extend({
cache: null, cache: null,
traditional: false, traditional: false,
headers: {}, headers: {},
crossDomain: null,
*/ */
accepts: { accepts: {
...@@ -604,7 +603,7 @@ jQuery.extend({ ...@@ -604,7 +603,7 @@ jQuery.extend({
s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax ); s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
// Determine if a cross-domain request is in order // Determine if a cross-domain request is in order
if ( !s.crossDomain ) { if ( s.crossDomain == null ) {
parts = rurl.exec( s.url.toLowerCase() ); parts = rurl.exec( s.url.toLowerCase() );
s.crossDomain = !!( parts && s.crossDomain = !!( parts &&
( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] || ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
......
...@@ -6,7 +6,8 @@ var rclass = /[\n\t\r]/g, ...@@ -6,7 +6,8 @@ var rclass = /[\n\t\r]/g,
rtype = /^(?:button|input)$/i, rtype = /^(?:button|input)$/i,
rfocusable = /^(?:button|input|object|select|textarea)$/i, rfocusable = /^(?:button|input|object|select|textarea)$/i,
rclickable = /^a(?:rea)?$/i, rclickable = /^a(?:rea)?$/i,
rradiocheck = /^(?:radio|checkbox)$/i; rradiocheck = /^(?:radio|checkbox)$/i,
formHook;
jQuery.fn.extend({ jQuery.fn.extend({
attr: function( name, value ) { attr: function( name, value ) {
...@@ -15,9 +16,21 @@ jQuery.fn.extend({ ...@@ -15,9 +16,21 @@ jQuery.fn.extend({
removeAttr: function( name ) { removeAttr: function( name ) {
return this.each(function() { return this.each(function() {
if ( this.nodeType === 1 ) { jQuery.removeAttr( this, name );
this.removeAttribute( 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({ ...@@ -36,10 +49,10 @@ jQuery.fn.extend({
}, },
addClass: function( value ) { addClass: function( value ) {
if ( jQuery.isFunction(value) ) { if ( jQuery.isFunction( value ) ) {
return this.each(function(i) { return this.each(function(i) {
var self = jQuery(this); 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({ ...@@ -275,80 +288,79 @@ jQuery.extend({
offset: true 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: { attrFix: {
"for": "htmlFor", // Always normalize to ensure hook usage
"class": "className",
readonly: "readOnly",
maxlength: "maxLength",
cellspacing: "cellSpacing",
rowspan: "rowSpan",
colspan: "colSpan",
tabindex: "tabIndex", tabindex: "tabIndex",
usemap: "useMap", readonly: "readOnly"
frameborder: "frameBorder"
}, },
attr: function( elem, name, value, pass ) { attr: function( elem, name, value, pass ) {
var nType = elem.nodeType;
// don't get/set attributes on text, comment and attribute nodes // 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; return undefined;
} }
if ( pass && name in jQuery.attrFn ) { 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 ( 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; return ret;
} else { } else {
// convert the value to a string (all browsers do this but IE) see #1070 elem.setAttribute( name, "" + value );
value = "" + value;
elem.setAttribute( name, value );
return value; return value;
} }
} else { } else {
if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem )) !== undefined ) { if ( hooks && "get" in hooks && notxml ) {
return ret; return hooks.get( elem, name );
} else { } 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 // Non-existent attributes return null, we normalize to undefined
return attr === null ? return ret === null ?
undefined : undefined :
attr; ret;
} }
} }
}, },
hasAttr: function( elem, name ) { removeAttr: function( elem, name ) {
// Blackberry 4.7 returns "" from getAttribute #6938 if ( elem.nodeType === 1 ) {
return elem.attributes[ name ] || (elem.hasAttribute && elem.hasAttribute( name )); 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: { attrHooks: {
type: { type: {
set: function( elem, value ) { set: function( elem, value ) {
...@@ -358,15 +370,14 @@ jQuery.extend({ ...@@ -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: { tabIndex: {
get: function( elem ) { 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 ? return attributeNode && attributeNode.specified ?
attributeNode.value : parseInt( attributeNode.value, 10 ) :
rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
0 : 0 :
undefined; undefined;
...@@ -374,11 +385,18 @@ jQuery.extend({ ...@@ -374,11 +385,18 @@ jQuery.extend({
} }
}, },
// TODO: Check to see if we really need any here.
propFix: {}, propFix: {},
prop: function( elem, name, value ) { 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 // Try to normalize/fix the name
name = notxml && jQuery.propFix[ name ] || name; name = notxml && jQuery.propFix[ name ] || name;
...@@ -386,7 +404,7 @@ jQuery.extend({ ...@@ -386,7 +404,7 @@ jQuery.extend({
hooks = jQuery.propHooks[ name ]; hooks = jQuery.propHooks[ name ];
if ( value !== undefined ) { 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; return ret;
} else { } else {
...@@ -394,7 +412,7 @@ jQuery.extend({ ...@@ -394,7 +412,7 @@ jQuery.extend({
} }
} else { } else {
if ( hooks && "get" in hooks && (ret = hooks.get( elem )) !== undefined ) { if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {
return ret; return ret;
} else { } else {
...@@ -406,12 +424,73 @@ jQuery.extend({ ...@@ -406,12 +424,73 @@ jQuery.extend({
propHooks: {} 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 // Some attributes require a special call on IE
if ( !jQuery.support.hrefNormalized ) { 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 ], { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
get: function( elem ) { 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 ) { ...@@ -420,9 +499,10 @@ if ( !jQuery.support.hrefNormalized ) {
if ( !jQuery.support.style ) { if ( !jQuery.support.style ) {
jQuery.attrHooks.style = { jQuery.attrHooks.style = {
get: function( elem ) { 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 ) { set: function( elem, value ) {
return (elem.style.cssText = "" + value); return (elem.style.cssText = "" + value);
} }
...@@ -432,10 +512,10 @@ if ( !jQuery.support.style ) { ...@@ -432,10 +512,10 @@ if ( !jQuery.support.style ) {
// Safari mis-reports the default selected property of an option // Safari mis-reports the default selected property of an option
// Accessing the parent's selectedIndex property fixes it // Accessing the parent's selectedIndex property fixes it
if ( !jQuery.support.optSelected ) { if ( !jQuery.support.optSelected ) {
jQuery.attrHooks.selected = { jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
get: function( elem ) { get: function( elem ) {
var parent = elem.parentNode; var parent = elem.parentNode;
if ( parent ) { if ( parent ) {
parent.selectedIndex; parent.selectedIndex;
...@@ -445,7 +525,7 @@ if ( !jQuery.support.optSelected ) { ...@@ -445,7 +525,7 @@ if ( !jQuery.support.optSelected ) {
} }
} }
} }
}; });
} }
})( jQuery ); })( jQuery );
...@@ -894,4 +894,4 @@ function doScrollCheck() { ...@@ -894,4 +894,4 @@ function doScrollCheck() {
// Expose jQuery to the global object // Expose jQuery to the global object
return jQuery; return jQuery;
})(); })();
\ No newline at end of file
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
var ralpha = /alpha\([^)]*\)/i, var ralpha = /alpha\([^)]*\)/i,
ropacity = /opacity=([^)]*)/, ropacity = /opacity=([^)]*)/,
rdashAlpha = /-([a-z])/ig, rdashAlpha = /-([a-z])/ig,
rupper = /([A-Z])/g, // fixed for IE9, see #8346
rupper = /([A-Z]|^ms)/g,
rnumpx = /^-?\d+(?:px)?$/i, rnumpx = /^-?\d+(?:px)?$/i,
rnum = /^-?\d/, rnum = /^-?\d/,
...@@ -240,6 +241,28 @@ if ( !jQuery.support.opacity ) { ...@@ -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 ) { if ( document.defaultView && document.defaultView.getComputedStyle ) {
getComputedStyle = function( elem, newName, name ) { getComputedStyle = function( elem, newName, name ) {
var ret, defaultView, computedStyle; var ret, defaultView, computedStyle;
......
...@@ -144,7 +144,10 @@ jQuery.extend({ ...@@ -144,7 +144,10 @@ jQuery.extend({
return function( value ) { return function( value ) {
args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
if ( !( --count ) ) { 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 ) );
} }
}; };
} }
......
...@@ -70,10 +70,10 @@ jQuery.event = { ...@@ -70,10 +70,10 @@ jQuery.event = {
} }
if ( !eventHandle ) { if ( !eventHandle ) {
elemData.handle = eventHandle = function() { elemData.handle = eventHandle = function( e ) {
// Handle the second event of a trigger and when // Handle the second event of a trigger and when
// an event is called after a page has unloaded // 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 ) : jQuery.event.handle.apply( eventHandle.elem, arguments ) :
undefined; undefined;
}; };
...@@ -380,7 +380,7 @@ jQuery.event = { ...@@ -380,7 +380,7 @@ jQuery.event = {
target[ "on" + targetType ] = null; target[ "on" + targetType ] = null;
} }
jQuery.event.triggered = true; jQuery.event.triggered = event.type;
target[ targetType ](); target[ targetType ]();
} }
...@@ -391,7 +391,7 @@ jQuery.event = { ...@@ -391,7 +391,7 @@ jQuery.event = {
target[ "on" + targetType ] = old; target[ "on" + targetType ] = old;
} }
jQuery.event.triggered = false; jQuery.event.triggered = undefined;
} }
} }
}, },
...@@ -661,7 +661,7 @@ var withinElement = function( event ) { ...@@ -661,7 +661,7 @@ var withinElement = function( event ) {
// Chrome does something similar, the parentNode property // Chrome does something similar, the parentNode property
// can be accessed but is null. // can be accessed but is null.
if ( parent !== document && !parent.parentNode ) { if ( parent && parent !== document && !parent.parentNode ) {
return; return;
} }
// Traverse up the tree // Traverse up the tree
...@@ -868,19 +868,33 @@ function trigger( type, elem, args ) { ...@@ -868,19 +868,33 @@ function trigger( type, elem, args ) {
// Create "bubbling" focus and blur events // Create "bubbling" focus and blur events
if ( document.addEventListener ) { if ( document.addEventListener ) {
jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { 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 ] = { jQuery.event.special[ fix ] = {
setup: function() { setup: function() {
this.addEventListener( orig, handler, true ); if ( attaches++ === 0 ) {
document.addEventListener( orig, handler, true );
}
}, },
teardown: function() { teardown: function() {
this.removeEventListener( orig, handler, true ); if ( --attaches === 0 ) {
document.removeEventListener( orig, handler, true );
}
} }
}; };
function handler( e ) { function handler( donor ) {
e = jQuery.event.fix( e ); // 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; e.type = fix;
return jQuery.event.handle.call( this, e ); e.originalEvent = {};
jQuery.event.trigger( e, null, e.target );
if ( e.isDefaultPrevented() ) {
donor.preventDefault();
}
} }
}); });
} }
......
...@@ -261,7 +261,9 @@ jQuery.fn.extend({ ...@@ -261,7 +261,9 @@ jQuery.fn.extend({
} }
}); });
} else { } 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 ) { ...@@ -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 // We do not need to do anything for non-Elements
if ( dest.nodeType !== 1 ) { if ( dest.nodeType !== 1 ) {
return; return;
...@@ -547,7 +549,8 @@ jQuery.extend({ ...@@ -547,7 +549,8 @@ jQuery.extend({
// Return the cloned set // Return the cloned set
return clone; return clone;
}, },
clean: function( elems, context, fragment, scripts ) { clean: function( elems, context, fragment, scripts ) {
context = context || document; context = context || document;
......
...@@ -37,8 +37,8 @@ if ( "getBoundingClientRect" in document.documentElement ) { ...@@ -37,8 +37,8 @@ if ( "getBoundingClientRect" in document.documentElement ) {
win = getWindow(doc), win = getWindow(doc),
clientTop = docElem.clientTop || body.clientTop || 0, clientTop = docElem.clientTop || body.clientTop || 0,
clientLeft = docElem.clientLeft || body.clientLeft || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
scrollTop = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ), scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop,
scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft), scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
top = box.top + scrollTop - clientTop, top = box.top + scrollTop - clientTop,
left = box.left + scrollLeft - clientLeft; left = box.left + scrollLeft - clientLeft;
...@@ -151,7 +151,6 @@ jQuery.offset = { ...@@ -151,7 +151,6 @@ jQuery.offset = {
this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop); this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
body.removeChild( container ); body.removeChild( container );
body = container = innerDiv = checkDiv = table = td = null;
jQuery.offset.initialize = jQuery.noop; jQuery.offset.initialize = jQuery.noop;
}, },
...@@ -181,10 +180,10 @@ jQuery.offset = { ...@@ -181,10 +180,10 @@ jQuery.offset = {
curOffset = curElem.offset(), curOffset = curElem.offset(),
curCSSTop = jQuery.css( elem, "top" ), curCSSTop = jQuery.css( elem, "top" ),
curCSSLeft = jQuery.css( elem, "left" ), 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; 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 ) { if ( calculatePosition ) {
curPosition = curElem.position(); curPosition = curElem.position();
} }
......
Subproject commit f12b9309269ba7e705a99efe099f86ed1fe98d58
...@@ -7,8 +7,9 @@ ...@@ -7,8 +7,9 @@
var div = document.createElement("div"); var div = document.createElement("div");
div.style.display = "none"; 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("*"), var all = div.getElementsByTagName("*"),
a = div.getElementsByTagName("a")[0], a = div.getElementsByTagName("a")[0],
select = document.createElement("select"), select = document.createElement("select"),
...@@ -33,8 +34,8 @@ ...@@ -33,8 +34,8 @@
htmlSerialize: !!div.getElementsByTagName("link").length, htmlSerialize: !!div.getElementsByTagName("link").length,
// Get the style information from getAttribute // Get the style information from getAttribute
// (IE uses .cssText insted) // (IE uses .cssText instead, and capitalizes all property names)
style: /red/.test( a.getAttribute("style") ), style: /top/.test( a.getAttribute("style") ),
// Make sure that URLs aren't manipulated // Make sure that URLs aren't manipulated
// (IE normalizes it by default) // (IE normalizes it by default)
...@@ -57,6 +58,9 @@ ...@@ -57,6 +58,9 @@
// Make sure that a selected-by-default option has a working selected property. // 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) // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
optSelected: opt.selected, 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 // Will be defined later
deleteExpando: true, deleteExpando: true,
...@@ -67,7 +71,8 @@ ...@@ -67,7 +71,8 @@
boxModel: null, boxModel: null,
inlineBlockNeedsLayout: false, inlineBlockNeedsLayout: false,
shrinkWrapBlocks: false, shrinkWrapBlocks: false,
reliableHiddenOffsets: true reliableHiddenOffsets: true,
reliableMarginRight: true
}; };
input.checked = true; input.checked = true;
...@@ -85,15 +90,15 @@ ...@@ -85,15 +90,15 @@
script = document.createElement("script"), script = document.createElement("script"),
id = "script" + jQuery.now(); 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 { try {
script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
} catch(e) {} } catch(e) {}
root.insertBefore( script, root.firstChild ); 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 ] ) { if ( window[ id ] ) {
_scriptEval = true; _scriptEval = true;
delete window[ id ]; delete window[ id ];
...@@ -102,8 +107,6 @@ ...@@ -102,8 +107,6 @@
} }
root.removeChild( script ); root.removeChild( script );
// release memory in IE
root = script = id = null;
} }
return _scriptEval; return _scriptEval;
...@@ -188,6 +191,17 @@ ...@@ -188,6 +191,17 @@
jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0;
div.innerHTML = ""; 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"; body.removeChild( div ).style.display = "none";
div = tds = null; div = tds = null;
}); });
...@@ -211,8 +225,6 @@ ...@@ -211,8 +225,6 @@
el.setAttribute(eventName, "return;"); el.setAttribute(eventName, "return;");
isSupported = typeof el[eventName] === "function"; isSupported = typeof el[eventName] === "function";
} }
el = null;
return isSupported; return isSupported;
}; };
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
<body> <body>
<div id="fixed-1" class="fixed"></div> <div id="fixed-1" class="fixed"></div>
<div id="fixed-2" 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="forceScroll"></div>
<div id="marker"></div> <div id="marker"></div>
<p class="instructions">Click the white box to move the marker to it.</p> <p class="instructions">Click the white box to move the marker to it.</p>
......
...@@ -203,6 +203,10 @@ Z</textarea> ...@@ -203,6 +203,10 @@ Z</textarea>
<select name="D4" disabled="disabled"> <select name="D4" disabled="disabled">
<option selected="selected" value="NO">NO</option> <option selected="selected" value="NO">NO</option>
</select> </select>
<input id="list-test" type="text" />
<datalist id="datalist">
<option value="option"></option>
</datalist>
</form> </form>
<div id="moretests"> <div id="moretests">
<form> <form>
......
Subproject commit d404faf8f587fcbe6b8907943022e6318dd51e0c
...@@ -492,7 +492,7 @@ test(".ajax() - hash", function() { ...@@ -492,7 +492,7 @@ test(".ajax() - hash", function() {
test("jQuery ajax - cross-domain detection", function() { test("jQuery ajax - cross-domain detection", function() {
expect( 5 ); expect( 6 );
var loc = document.location, var loc = document.location,
otherPort = loc.port === 666 ? 667 : 666, otherPort = loc.port === 666 ? 667 : 666,
...@@ -508,6 +508,7 @@ test("jQuery ajax - cross-domain detection", function() { ...@@ -508,6 +508,7 @@ test("jQuery ajax - cross-domain detection", function() {
}); });
jQuery.ajax({ jQuery.ajax({
dataType: "jsonp",
url: 'app:/path', url: 'app:/path',
beforeSend: function( _ , s ) { beforeSend: function( _ , s ) {
ok( s.crossDomain , "Adobe AIR app:/ URL detected as cross-domain" ); ok( s.crossDomain , "Adobe AIR app:/ URL detected as cross-domain" );
...@@ -533,6 +534,15 @@ test("jQuery ajax - cross-domain detection", function() { ...@@ -533,6 +534,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({ jQuery.ajax({
dataType: "jsonp", dataType: "jsonp",
url: loc.protocol + "//" + loc.host, url: loc.protocol + "//" + loc.host,
......
This diff is collapsed.
...@@ -333,3 +333,15 @@ test("internal ref to elem.runtimeStyle (bug #7608)", function () { ...@@ -333,3 +333,15 @@ test("internal ref to elem.runtimeStyle (bug #7608)", function () {
ok( result, "elem.runtimeStyle does not throw exception" ); 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");
});
...@@ -683,6 +683,20 @@ test("hover()", function() { ...@@ -683,6 +683,20 @@ test("hover()", function() {
equals( times, 4, "hover handlers fired" ); 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() { test("trigger() shortcuts", function() {
expect(6); expect(6);
...@@ -1966,6 +1980,36 @@ test("window resize", function() { ...@@ -1966,6 +1980,36 @@ test("window resize", function() {
ok( !jQuery._data(window, "__events__"), "Make sure all the events are gone." ); 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() { test("jQuery(function($) {})", function() {
stop(); stop();
......
...@@ -739,7 +739,7 @@ test("insertAfter(String|Element|Array&lt;Element&gt;|jQuery)", function() { ...@@ -739,7 +739,7 @@ test("insertAfter(String|Element|Array&lt;Element&gt;|jQuery)", function() {
}); });
var testReplaceWith = function(val) { var testReplaceWith = function(val) {
expect(20); expect(21);
jQuery('#yahoo').replaceWith(val( '<b id="replace">buga</b>' )); jQuery('#yahoo').replaceWith(val( '<b id="replace">buga</b>' ));
ok( jQuery("#replace")[0], 'Replace element with string' ); ok( jQuery("#replace")[0], 'Replace element with string' );
ok( !jQuery("#yahoo")[0], 'Verify that original element is gone, after string' ); ok( !jQuery("#yahoo")[0], 'Verify that original element is gone, after string' );
...@@ -800,6 +800,9 @@ var testReplaceWith = function(val) { ...@@ -800,6 +800,9 @@ var testReplaceWith = function(val) {
equals( set[0].nodeName.toLowerCase(), "span", "Replace the disconnected node." ); equals( set[0].nodeName.toLowerCase(), "span", "Replace the disconnected node." );
equals( set.length, 1, "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"); var $div = jQuery("<div class='replacewith'></div>").appendTo("body");
// TODO: Work on jQuery(...) inline script execution // TODO: Work on jQuery(...) inline script execution
//$div.replaceWith("<div class='replacewith'></div><script>" + //$div.replaceWith("<div class='replacewith'></div><script>" +
...@@ -827,7 +830,7 @@ test("replaceWith(String|Element|Array&lt;Element&gt;|jQuery)", function() { ...@@ -827,7 +830,7 @@ test("replaceWith(String|Element|Array&lt;Element&gt;|jQuery)", function() {
test("replaceWith(Function)", function() { test("replaceWith(Function)", function() {
testReplaceWith(functionReturningObj); testReplaceWith(functionReturningObj);
expect(21); expect(22);
var y = jQuery("#yahoo")[0]; var y = jQuery("#yahoo")[0];
...@@ -1006,7 +1009,7 @@ test("clone()", function() { ...@@ -1006,7 +1009,7 @@ test("clone()", function() {
}); });
test("clone(form element) (Bug #3879, #6655)", 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>"); 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" ); 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() { ...@@ -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.is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
equals( clone[0].defaultValue, "foo", "Checked input defaultValue 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'>"); element = jQuery("<input type='text' value='foo'>");
clone = element.clone(); clone = element.clone();
......
...@@ -265,7 +265,7 @@ testoffset("static", function( jQuery ) { ...@@ -265,7 +265,7 @@ testoffset("static", function( jQuery ) {
}); });
testoffset("fixed", function( jQuery ) { testoffset("fixed", function( jQuery ) {
expect(28); expect(30);
jQuery.offset.initialize(); jQuery.offset.initialize();
...@@ -320,6 +320,17 @@ testoffset("fixed", function( jQuery ) { ...@@ -320,6 +320,17 @@ testoffset("fixed", function( jQuery ) {
ok( true, 'Fixed position is not supported' ); 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 ) { testoffset("table", function( jQuery ) {
...@@ -422,7 +433,7 @@ test("offsetParent", function(){ ...@@ -422,7 +433,7 @@ test("offsetParent", function(){
equals( div[1], jQuery("#nothiddendiv")[0], "The div is the offsetParent." ); equals( div[1], jQuery("#nothiddendiv")[0], "The div is the offsetParent." );
}); });
function testoffset(name, fn) { function testoffset( name, fn ) {
test(name, function() { test(name, function() {
// pause execution for now // pause execution for now
...@@ -447,7 +458,7 @@ function testoffset(name, fn) { ...@@ -447,7 +458,7 @@ function testoffset(name, fn) {
function loadFixture() { function loadFixture() {
var src = './data/offset/' + name + '.html?' + parseInt( Math.random()*1000, 10 ), var src = './data/offset/' + name + '.html?' + parseInt( Math.random()*1000, 10 ),
iframe = jQuery('<iframe />').css({ 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]; }).appendTo('body')[0];
iframe.contentWindow.location = src; iframe.contentWindow.location = src;
return iframe; return iframe;
......
1.5.2pre 1.6pre
\ No newline at end of file \ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment