Merge branch 'master' into attrhooks.1.6v2

This commit is contained in:
timmywil 2011-04-10 16:26:39 -04:00
commit c10a76ec71
23 changed files with 1054 additions and 550 deletions

View file

@ -56,6 +56,89 @@ Sometimes, the various git repositories get into an inconsistent state where bui
(usually this results in the jquery.js or jquery.min.js being 0 bytes). If this happens, run `make clean`, then (usually this results in the jquery.js or jquery.min.js being 0 bytes). If this happens, run `make clean`, then
run `make` again. run `make` again.
Git for dummies
---------------
As the source code is handled by the version control system Git, it's useful to know some features used.
### Submodules ###
The repository uses submodules, which normally are handles directly by the Makefile, but sometimes you want to
be able to work with them manually.
Following are the steps to manually get the submodules:
1. `git clone https://github.com/jquery/jquery.git`
2. `git submodule init`
3. `git submodule update`
Or:
1. `git clone https://github.com/jquery/jquery.git`
2. `git submodule update --init`
Or:
1. `git clone --recursive https://github.com/jquery/jquery.git`
If you want to work inside a submodule, it is possible, but first you need to checkout a branch:
1. `cd src/sizzle`
2. `git checkout master`
After you've commited your changes to the submodule, you'll update the jquery project to point to the new commit,
but remember to push the submodule changes before pushing the new jquery commit:
1. `cd src/sizzle`
2. `git push origin master`
3. `cd ..`
4. `git add src/sizzle`
5. `git commit`
The makefile has some targets to simplify submodule handling:
#### `make update_submodules` ####
checks out the commit pointed to byu jquery, but merges your local changes, if any. This target is executed
when you are doing a normal `make`.
#### `make pull_submodules` ####
updates the content of the submoduels to what is probably the latest upstream code
#### `make pull` ####
make a `make pull_submodules` and after that a `git pull`. if you have no remote tracking in your master branch, you can
execute this command as `make pull REMOTE=origin BRANCH=master` instead.
### cleaning ###
If you want to purge your working directory back to the status of upstream, following commands can be used (remember everything you've worked on is gone after these):
1. `git reset --hard upstream/master`
2. `git clean -fdx`
### rebasing ###
For feature/topic branches, you should always used the `--rebase` flag to `git pull`, or if you are usually handling many temporary "to be in a github pull request" branches, run following to automate this:
* `git config branch.autosetuprebase local` (see `man git-config` for more information)
### handling merge conflicts ###
If you're getting merge conflicts when merging, instead of editing the conflicted files manually, you can use the feature
`git mergetool`. Even though the default tool `xxdiff` looks awful/old, it's rather useful.
Following are some commands that can be used there:
* `Ctrl + Alt + M` - automerge as much as possible
* `b` - jump to next merge conflict
* `s` - change the order of the conflicted lines
* `u` - undo an merge
* `left mouse button` - mark a block to be the winner
* `middle mouse button` - mark a line to be the winner
* `Ctrl + S` - save
* `Ctrl + Q` - quit
Questions? Questions?
---------- ----------

View file

@ -53,7 +53,7 @@ jQuery.ajaxTransport( "script", function(s) {
// Attach handlers for all browsers // Attach handlers for all browsers
script.onload = script.onreadystatechange = function( _, isAbort ) { script.onload = script.onreadystatechange = function( _, isAbort ) {
if ( !script.readyState || /loaded|complete/.test( script.readyState ) ) { if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
// Handle memory leak in IE // Handle memory leak in IE
script.onload = script.onreadystatechange = null; script.onload = script.onreadystatechange = null;

View file

@ -34,6 +34,20 @@ jQuery.fn.extend({
}); });
}, },
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 ) {}
});
},
addClass: function( value ) { addClass: function( value ) {
if ( jQuery.isFunction( value ) ) { if ( jQuery.isFunction( value ) ) {
return this.each(function(i) { return this.each(function(i) {

View file

@ -17,7 +17,7 @@ var jQuery = function( selector, context ) {
// A simple way to check for HTML strings or ID strings // A simple way to check for HTML strings or ID strings
// (both of which we optimize for) // (both of which we optimize for)
quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
// Check if a string has a non-whitespace character in it // Check if a string has a non-whitespace character in it
rnotwhite = /\S/, rnotwhite = /\S/,
@ -96,7 +96,12 @@ jQuery.fn = jQuery.prototype = {
// Handle HTML strings // Handle HTML strings
if ( typeof selector === "string" ) { if ( typeof selector === "string" ) {
// Are we dealing with HTML string or an ID? // Are we dealing with HTML string or an ID?
if ( selector.length > 1024 ) {
// Assume very large strings are HTML and skip the regex check
match = [ null, selector, null ];
} else {
match = quickExpr.exec( selector ); match = quickExpr.exec( selector );
}
// Verify a match, and that no context was specified for #id // Verify a match, and that no context was specified for #id
if ( match && (match[1] || !context) ) { if ( match && (match[1] || !context) ) {
@ -369,15 +374,19 @@ jQuery.extend({
// the ready event fires. See #6781 // the ready event fires. See #6781
readyWait: 1, readyWait: 1,
// Hold (or release) the ready event
holdReady: function( hold ) {
if ( hold ) {
jQuery.readyWait++;
} else {
jQuery.ready( true );
}
},
// Handle when the DOM is ready // Handle when the DOM is ready
ready: function( wait ) { ready: function( wait ) {
// A third-party is pushing the ready event forwards // Either a released hold or an DOMready/load event and not yet ready
if ( wait === true ) { if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
jQuery.readyWait--;
}
// Make sure that the DOM is not already loaded
if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if ( !document.body ) { if ( !document.body ) {
return setTimeout( jQuery.ready, 1 ); return setTimeout( jQuery.ready, 1 );
@ -515,20 +524,21 @@ jQuery.extend({
// Make sure leading/trailing whitespace is removed (IE can't handle it) // Make sure leading/trailing whitespace is removed (IE can't handle it)
data = jQuery.trim( data ); data = jQuery.trim( data );
// Attempt to parse using the native JSON parser first
if ( window.JSON && window.JSON.parse ) {
return window.JSON.parse( data );
}
// Make sure the incoming data is actual JSON // Make sure the incoming data is actual JSON
// Logic borrowed from http://json.org/json2.js // Logic borrowed from http://json.org/json2.js
if ( rvalidchars.test( data.replace( rvalidescape, "@" ) if ( rvalidchars.test( data.replace( rvalidescape, "@" )
.replace( rvalidtokens, "]" ) .replace( rvalidtokens, "]" )
.replace( rvalidbraces, "")) ) { .replace( rvalidbraces, "")) ) {
// Try to use the native JSON parser first return (new Function( "return " + data ))();
return window.JSON && window.JSON.parse ?
window.JSON.parse( data ) :
(new Function("return " + data))();
} else {
jQuery.error( "Invalid JSON: " + data );
} }
jQuery.error( "Invalid JSON: " + data );
}, },
// Cross-browser xml parsing // Cross-browser xml parsing
@ -555,24 +565,17 @@ jQuery.extend({
noop: function() {}, noop: function() {},
// Evalulates a script in a global context // Evaluates a script in a global context
// Workarounds based on findings by Jim Driscoll
// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
globalEval: function( data ) { globalEval: function( data ) {
if ( data && rnotwhite.test( data ) ) { if ( data && rnotwhite.test( data ) ) {
// Inspired by code by Andrea Giammarchi // We use execScript on Internet Explorer
// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html // We use an anonymous function so that context is window
var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement, // rather than jQuery in Firefox
script = document.createElement( "script" ); ( window.execScript || function( data ) {
window[ "eval" ].call( window, data );
if ( jQuery.support.scriptEval() ) { } )( data );
script.appendChild( document.createTextNode( data ) );
} else {
script.text = data;
}
// Use insertBefore instead of appendChild to circumvent an IE6 bug.
// This arises when a base node is used (#2709).
head.insertBefore( script, head.firstChild );
head.removeChild( script );
} }
}, },
@ -655,8 +658,9 @@ jQuery.extend({
}, },
inArray: function( elem, array ) { inArray: function( elem, array ) {
if ( array.indexOf ) {
return array.indexOf( elem ); if ( indexOf ) {
return indexOf.call( array, elem );
} }
for ( var i = 0, length = array.length; i < length; i++ ) { for ( var i = 0, length = array.length; i < length; i++ ) {
@ -840,12 +844,6 @@ if ( jQuery.browser.webkit ) {
jQuery.browser.safari = true; jQuery.browser.safari = true;
} }
if ( indexOf ) {
jQuery.inArray = function( elem, array ) {
return indexOf.call( array, elem );
};
}
// IE doesn't match non-breaking spaces with \s // IE doesn't match non-breaking spaces with \s
if ( rnotwhite.test( "\xA0" ) ) { if ( rnotwhite.test( "\xA0" ) ) {
trimLeft = /^[\s\xA0]+/; trimLeft = /^[\s\xA0]+/;

View file

@ -7,6 +7,8 @@ var ralpha = /alpha\([^)]*\)/i,
rupper = /([A-Z]|^ms)/g, rupper = /([A-Z]|^ms)/g,
rnumpx = /^-?\d+(?:px)?$/i, rnumpx = /^-?\d+(?:px)?$/i,
rnum = /^-?\d/, rnum = /^-?\d/,
rrelNum = /^[+\-]=/,
rrelNumFilter = /[^+\-\.\de]+/g,
cssShow = { position: "absolute", visibility: "hidden", display: "block" }, cssShow = { position: "absolute", visibility: "hidden", display: "block" },
cssWidth = [ "Left", "Right" ], cssWidth = [ "Left", "Right" ],
@ -75,20 +77,27 @@ jQuery.extend({
} }
// Make sure that we're working with the right name // Make sure that we're working with the right name
var ret, origName = jQuery.camelCase( name ), var ret, type, origName = jQuery.camelCase( name ),
style = elem.style, hooks = jQuery.cssHooks[ origName ]; style = elem.style, hooks = jQuery.cssHooks[ origName ];
name = jQuery.cssProps[ origName ] || origName; name = jQuery.cssProps[ origName ] || origName;
// Check if we're setting a value // Check if we're setting a value
if ( value !== undefined ) { if ( value !== undefined ) {
type = typeof value;
// Make sure that NaN and null values aren't set. See: #7116 // Make sure that NaN and null values aren't set. See: #7116
if ( typeof value === "number" && isNaN( value ) || value == null ) { if ( type === "number" && isNaN( value ) || value == null ) {
return; return;
} }
// convert relative number strings (+= or -=) to relative numbers. #7345
if ( type === "string" && rrelNum.test( value ) ) {
value = +value.replace( rrelNumFilter, '' ) + parseFloat( jQuery.css( elem, name ) );
}
// If a number was passed in, add 'px' to the (except for certain CSS properties) // If a number was passed in, add 'px' to the (except for certain CSS properties)
if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) { if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
value += "px"; value += "px";
} }

View file

@ -1,6 +1,7 @@
(function( jQuery ) { (function( jQuery ) {
var rbrace = /^(?:\{.*\}|\[.*\])$/; var rbrace = /^(?:\{.*\}|\[.*\])$/,
rmultiDash = /([a-z])([A-Z])/g;
jQuery.extend({ jQuery.extend({
cache: {}, cache: {},
@ -228,7 +229,8 @@ jQuery.fn.extend({
name = attr[i].name; name = attr[i].name;
if ( name.indexOf( "data-" ) === 0 ) { if ( name.indexOf( "data-" ) === 0 ) {
name = name.substr( 5 ); name = jQuery.camelCase( name.substring(5) );
dataAttr( this[0], name, data[ name ] ); dataAttr( this[0], name, data[ name ] );
} }
} }
@ -282,7 +284,9 @@ function dataAttr( elem, key, data ) {
// If nothing was found internally, try to fetch any // If nothing was found internally, try to fetch any
// data from the HTML5 data-* attribute // data from the HTML5 data-* attribute
if ( data === undefined && elem.nodeType === 1 ) { if ( data === undefined && elem.nodeType === 1 ) {
data = elem.getAttribute( "data-" + key ); name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase();
data = elem.getAttribute( name );
if ( typeof data === "string" ) { if ( typeof data === "string" ) {
try { try {

View file

@ -1,7 +1,7 @@
(function( jQuery ) { (function( jQuery ) {
var // Promise methods var // Promise methods
promiseMethods = "then done fail isResolved isRejected promise".split( " " ), promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ),
// Static reference to slice // Static reference to slice
sliceDeferred = [].slice; sliceDeferred = [].slice;
@ -100,10 +100,37 @@ jQuery.extend({
deferred.done( doneCallbacks ).fail( failCallbacks ); deferred.done( doneCallbacks ).fail( failCallbacks );
return this; return this;
}, },
always: function() {
return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );
},
fail: failDeferred.done, fail: failDeferred.done,
rejectWith: failDeferred.resolveWith, rejectWith: failDeferred.resolveWith,
reject: failDeferred.resolve, reject: failDeferred.resolve,
isRejected: failDeferred.isResolved, isRejected: failDeferred.isResolved,
pipe: function( fnDone, fnFail ) {
return jQuery.Deferred(function( newDefer ) {
jQuery.each( {
done: [ fnDone, "resolve" ],
fail: [ fnFail, "reject" ]
}, function( handler, data ) {
var fn = data[ 0 ],
action = data[ 1 ],
returned;
if ( jQuery.isFunction( fn ) ) {
deferred[ handler ](function() {
returned = fn.apply( this, arguments );
if ( jQuery.isFunction( returned.promise ) ) {
returned.promise().then( newDefer.resolve, newDefer.reject );
} else {
newDefer[ action ]( returned );
}
});
} else {
deferred[ handler ]( newDefer[ action ] );
}
});
}).promise();
},
// Get a promise for this deferred // Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object // If obj is provided, the promise aspect is added to the object
promise: function( obj ) { promise: function( obj ) {

17
src/effects.js vendored
View file

@ -11,7 +11,17 @@ var elemdisplay = {},
[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ], [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
// opacity animations // opacity animations
[ "opacity" ] [ "opacity" ]
]; ],
fxNow;
function clearFxNow() {
fxNow = undefined;
}
function createFxNow() {
setTimeout( clearFxNow, 0 );
return ( fxNow = jQuery.now() );
}
jQuery.fn.extend({ jQuery.fn.extend({
show: function( speed, easing, callback ) { show: function( speed, easing, callback ) {
@ -349,7 +359,7 @@ jQuery.fx.prototype = {
var self = this, var self = this,
fx = jQuery.fx; fx = jQuery.fx;
this.startTime = jQuery.now(); this.startTime = fxNow || createFxNow();
this.start = from; this.start = from;
this.end = to; this.end = to;
this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" ); this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
@ -394,7 +404,8 @@ jQuery.fx.prototype = {
// Each step of an animation // Each step of an animation
step: function( gotoEnd ) { step: function( gotoEnd ) {
var t = jQuery.now(), done = true; var t = fxNow || createFxNow(),
done = true;
if ( gotoEnd || t >= this.options.duration + this.startTime ) { if ( gotoEnd || t >= this.options.duration + this.startTime ) {
this.now = this.end; this.now = this.end;

View file

@ -71,8 +71,8 @@ jQuery.event = {
if ( !eventHandle ) { if ( !eventHandle ) {
elemData.handle = eventHandle = function( e ) { elemData.handle = eventHandle = function( e ) {
// Handle the second event of a trigger and when // Discard the second event of a jQuery.event.trigger() and
// an event is called after a page has unloaded // when an event is called after a page has unloaded
return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? 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;
@ -143,7 +143,7 @@ jQuery.event = {
// Add the function to the element's handler list // Add the function to the element's handler list
handlers.push( handleObj ); handlers.push( handleObj );
// Keep track of which events have been used, for global triggering // Keep track of which events have been used, for event optimization
jQuery.event.global[ type ] = true; jQuery.event.global[ type ] = true;
} }
@ -277,13 +277,11 @@ jQuery.event = {
} }
}, },
// bubbling is internal trigger: function( event, data, elem ) {
trigger: function( event, data, elem /*, bubbling */ ) {
// Event object or event type // Event object or event type
var type = event.type || event, var type = event.type || event,
bubbling = arguments[3]; namespaces = [];
if ( !bubbling ) {
event = typeof event === "object" ? event = typeof event === "object" ?
// jQuery.Event object // jQuery.Event object
event[ jQuery.expando ] ? event : event[ jQuery.expando ] ? event :
@ -293,16 +291,25 @@ jQuery.event = {
jQuery.Event(type); jQuery.Event(type);
if ( type.indexOf("!") >= 0 ) { if ( type.indexOf("!") >= 0 ) {
// Exclusive events trigger only for the bare event type (no namespaces)
event.type = type = type.slice(0, -1); event.type = type = type.slice(0, -1);
event.exclusive = true; event.exclusive = true;
} }
if ( type.indexOf(".") >= 0 ) {
// Namespaced trigger; create a regexp to match event type in handle()
namespaces = type.split(".");
event.type = type = namespaces.shift();
namespaces.sort();
}
event.namespace = namespaces.join(".");
event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)");
// Handle a global trigger // Handle a global trigger
if ( !elem ) { if ( !elem ) {
// Don't bubble custom events when global (to avoid too much overhead) // Don't bubble custom events when global (to avoid too much overhead)
event.stopPropagation(); event.stopPropagation();
// Only trigger if we've ever bound an event for it // Save some time, only trigger if we've ever bound an event for this type
if ( jQuery.event.global[ type ] ) { if ( jQuery.event.global[ type ] ) {
// XXX This code smells terrible. event.js should not be directly // XXX This code smells terrible. event.js should not be directly
// inspecting the data cache // inspecting the data cache
@ -317,78 +324,72 @@ jQuery.event = {
} }
}); });
} }
return;
} }
// Handle triggering a single element // Don't do events on text and comment nodes
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
// don't do events on text and comment nodes return;
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
return undefined;
} }
// Clean up in case it is reused // Clean up the event in case it is being reused
event.result = undefined; event.result = undefined;
event.target = elem; event.target = elem;
// Clone the incoming data, if any // Clone any incoming data and prepend the event, creating the handler arg list
data = jQuery.makeArray( data ); data = jQuery.makeArray( data );
data.unshift( event ); data.unshift( event );
}
event.currentTarget = elem; var cur = elem,
// IE doesn't like method names with a colon (#3533, #8272)
ontype = type.indexOf(":") < 0? "on" + type : "";
// Trigger the event, it is assumed that "handle" is a function // Fire event on the current element, then bubble up the DOM tree
var handle = jQuery._data( elem, "handle" ); do {
var handle = jQuery._data( cur, "handle" );
event.currentTarget = cur;
if ( handle ) { if ( handle ) {
handle.apply( elem, data ); handle.apply( cur, data );
} }
var parent = elem.parentNode || elem.ownerDocument;
// Trigger an inline bound script // Trigger an inline bound script
try { if ( ontype &&jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {
if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
event.result = false; event.result = false;
event.preventDefault(); event.preventDefault();
} }
}
// prevent IE from throwing an error for some elements with some event types, see #3533 // Bubble up to document, then to window
} catch (inlineError) {} cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;
} while ( cur && !event.isPropagationStopped() );
if ( !event.isPropagationStopped() && parent ) { // If nobody prevented the default action, do it now
jQuery.event.trigger( event, data, parent, true ); if ( !event.isDefaultPrevented() ) {
} else if ( !event.isDefaultPrevented() ) {
var old, var old,
target = event.target, special = jQuery.event.special[ type ] || {};
targetType = type.replace( rnamespaces, "" ),
isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
special = jQuery.event.special[ targetType ] || {};
if ( (!special._default || special._default.call( elem, event ) === false) && if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&
!isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
// Call a native DOM method on the target with the same name name as the event.
// Can't use an .isFunction)() check here because IE6/7 fails that test.
// IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.
try { try {
if ( target[ targetType ] ) { if ( ontype && elem[ type ] ) {
// Make sure that we don't accidentally re-trigger the onFOO events // Don't re-trigger an onFOO event when we call its FOO() method
old = target[ "on" + targetType ]; old = elem[ ontype ];
if ( old ) { if ( old ) {
target[ "on" + targetType ] = null; elem[ ontype ] = null;
} }
jQuery.event.triggered = event.type; jQuery.event.triggered = type;
target[ targetType ](); elem[ type ]();
} }
} catch ( ieError ) {}
// prevent IE from throwing an error for some elements with some event types, see #3533
} catch (triggerError) {}
if ( old ) { if ( old ) {
target[ "on" + targetType ] = old; elem[ ontype ] = old;
} }
jQuery.event.triggered = undefined; jQuery.event.triggered = undefined;
@ -397,38 +398,22 @@ jQuery.event = {
}, },
handle: function( event ) { handle: function( event ) {
var all, handlers, namespaces, namespace_re, events, event = jQuery.event.fix( event || window.event );
namespace_sort = [], // Snapshot the handlers list since a called handler may add/remove events.
var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0),
run_all = !event.exclusive && !event.namespace,
args = jQuery.makeArray( arguments ); args = jQuery.makeArray( arguments );
event = args[0] = jQuery.event.fix( event || window.event ); // Use the fix-ed Event rather than the (read-only) native event
args[0] = event;
event.currentTarget = this; event.currentTarget = this;
// Namespaced event handlers
all = event.type.indexOf(".") < 0 && !event.exclusive;
if ( !all ) {
namespaces = event.type.split(".");
event.type = namespaces.shift();
namespace_sort = namespaces.slice(0).sort();
namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
}
event.namespace = event.namespace || namespace_sort.join(".");
events = jQuery._data(this, "events");
handlers = (events || {})[ event.type ];
if ( events && handlers ) {
// Clone the handlers to prevent manipulation
handlers = handlers.slice(0);
for ( var j = 0, l = handlers.length; j < l; j++ ) { for ( var j = 0, l = handlers.length; j < l; j++ ) {
var handleObj = handlers[ j ]; var handleObj = handlers[ j ];
// Filter the functions by class // Triggered event must 1) be non-exclusive and have no namespace, or
if ( all || namespace_re.test( handleObj.namespace ) ) { // 2) have namespace(s) a subset or equal to those in the bound event.
if ( run_all || event.namespace_re.test( handleObj.namespace ) ) {
// Pass in a reference to the handler function itself // Pass in a reference to the handler function itself
// So that we can later remove it // So that we can later remove it
event.handler = handleObj.handler; event.handler = handleObj.handler;
@ -450,8 +435,6 @@ jQuery.event = {
} }
} }
} }
}
return event.result; return event.result;
}, },
@ -490,8 +473,9 @@ jQuery.event = {
// Calculate pageX/Y if missing and clientX/Y available // Calculate pageX/Y if missing and clientX/Y available
if ( event.pageX == null && event.clientX != null ) { if ( event.pageX == null && event.clientX != null ) {
var doc = document.documentElement, var eventDocument = event.target.ownerDocument || document,
body = document.body; doc = eventDocument.documentElement,
body = eventDocument.body;
event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
@ -866,7 +850,7 @@ function trigger( type, elem, args ) {
} }
// Create "bubbling" focus and blur events // Create "bubbling" focus and blur events
if ( document.addEventListener ) { if ( !jQuery.support.focusinBubbles ) {
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 // Attach a single capturing handler while someone wants focusin/focusout
@ -1027,8 +1011,8 @@ jQuery.each(["live", "die"], function( i, name ) {
return this; return this;
} }
if ( jQuery.isFunction( data ) ) { if ( data === false || jQuery.isFunction( data ) ) {
fn = data; fn = data || returnFalse;
data = undefined; data = undefined;
} }

View file

@ -28,7 +28,8 @@ jQuery.extend({
type = type || "fx"; type = type || "fx";
var queue = jQuery.queue( elem, type ), var queue = jQuery.queue( elem, type ),
fn = queue.shift(); fn = queue.shift(),
defer;
// If the fx queue is dequeued, always remove the progress sentinel // If the fx queue is dequeued, always remove the progress sentinel
if ( fn === "inprogress" ) { if ( fn === "inprogress" ) {
@ -49,6 +50,17 @@ jQuery.extend({
if ( !queue.length ) { if ( !queue.length ) {
jQuery.removeData( elem, type + "queue", true ); jQuery.removeData( elem, type + "queue", true );
// Look if we have observers and resolve if needed
if (( defer = jQuery.data( elem, type + "defer", undefined, true ) )) {
// Give room for hard-coded callbacks to fire first
// and eventually add another animation on the element
setTimeout( function() {
if ( !jQuery.data( elem, type + "queue", undefined, true ) ) {
jQuery.removeData( elem, type + "defer", true );
defer.resolve();
}
}, 0 );
}
} }
} }
}); });
@ -93,6 +105,37 @@ jQuery.fn.extend({
clearQueue: function( type ) { clearQueue: function( type ) {
return this.queue( type || "fx", [] ); return this.queue( type || "fx", [] );
},
// Get a promise resolved when queues of a certain type
// are emptied (fx is the type by default)
promise: function( type, object ) {
if ( typeof type !== "string" ) {
object = type;
type = undefined;
}
type = type || "fx";
var defer = jQuery.Deferred(),
elements = this,
i = elements.length,
count = 1,
deferDataKey = type + "defer",
queueDataKey = type + "queue";
function resolve() {
if ( !( --count ) ) {
defer.resolveWith( elements, [ elements ] );
}
}
while( i-- ) {
if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
jQuery.data( elements[ i ], queueDataKey, undefined, true ) &&
jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {
count++;
tmp.done( resolve );
}
}
resolve();
return defer.promise();
} }
}); });

@ -1 +1 @@
Subproject commit f12b9309269ba7e705a99efe099f86ed1fe98d58 Subproject commit 80f2b81d1fbc13d62afb91cb87e1452fbbec1ef4

View file

@ -1,29 +1,42 @@
(function( jQuery ) { (function( jQuery ) {
(function() { jQuery.support = (function() {
jQuery.support = {}; var div = document.createElement( "div" ),
all,
a,
select,
opt,
input,
support,
fragment,
body,
bodyStyle,
tds,
events,
eventName,
i,
isSupported;
var div = document.createElement("div"); // Preliminary tests
div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
div.style.display = "none"; all = div.getElementsByTagName( "*" );
div.setAttribute("className", "t"); a = div.getElementsByTagName( "a" )[ 0 ];
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"),
opt = select.appendChild( document.createElement("option") ),
input = div.getElementsByTagName("input")[0];
// Can't get basic test support // Can't get basic test support
if ( !all || !all.length || !a ) { if ( !all || !all.length || !a ) {
return; return {};
} }
jQuery.support = { // First batch of supports tests
select = document.createElement( "select" );
opt = select.appendChild( document.createElement("option") );
input = div.getElementsByTagName( "input" )[ 0 ];
support = {
// IE strips leading whitespace when .innerHTML is used // IE strips leading whitespace when .innerHTML is used
leadingWhitespace: div.firstChild.nodeType === 3, leadingWhitespace: ( div.firstChild.nodeType === 3 ),
// Make sure that tbody elements aren't automatically inserted // Make sure that tbody elements aren't automatically inserted
// IE will insert them into empty tables // IE will insert them into empty tables
@ -34,12 +47,12 @@
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 instead, and capitalizes all property names) // (IE uses .cssText instead)
style: /top/.test( a.getAttribute("style") ), style: /red/.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)
hrefNormalized: a.getAttribute("href") === "/a", hrefNormalized: ( a.getAttribute( "href" ) === "/a" ),
// Make sure that element opacity exists // Make sure that element opacity exists
// (IE uses filter instead) // (IE uses filter instead)
@ -53,7 +66,7 @@
// Make sure that if no value is specified for a checkbox // Make sure that if no value is specified for a checkbox
// that it defaults to "on". // that it defaults to "on".
// (WebKit defaults to "" instead) // (WebKit defaults to "" instead)
checkOn: input.value === "on", checkOn: ( input.value === "on" ),
// 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)
@ -63,97 +76,72 @@
getSetAttribute: div.className !== "t", getSetAttribute: div.className !== "t",
// Will be defined later // Will be defined later
submitBubbles: true,
changeBubbles: true,
focusinBubbles: false,
deleteExpando: true, deleteExpando: true,
optDisabled: false,
checkClone: false,
noCloneEvent: true, noCloneEvent: true,
noCloneChecked: true,
boxModel: null,
inlineBlockNeedsLayout: false, inlineBlockNeedsLayout: false,
shrinkWrapBlocks: false, shrinkWrapBlocks: false,
reliableHiddenOffsets: true,
reliableMarginRight: true reliableMarginRight: true
}; };
// Make sure checked status is properly cloned
input.checked = true; input.checked = true;
jQuery.support.noCloneChecked = input.cloneNode( true ).checked; support.noCloneChecked = input.cloneNode( true ).checked;
// Make sure that the options inside disabled selects aren't marked as disabled // Make sure that the options inside disabled selects aren't marked as disabled
// (WebKit marks them as diabled) // (WebKit marks them as disabled)
select.disabled = true; select.disabled = true;
jQuery.support.optDisabled = !opt.disabled; support.optDisabled = !opt.disabled;
var _scriptEval = null;
jQuery.support.scriptEval = function() {
if ( _scriptEval === null ) {
var root = document.documentElement,
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 );
if ( window[ id ] ) {
_scriptEval = true;
delete window[ id ];
} else {
_scriptEval = false;
}
root.removeChild( script );
}
return _scriptEval;
};
// Test to see if it's possible to delete an expando from an element // Test to see if it's possible to delete an expando from an element
// Fails in Internet Explorer // Fails in Internet Explorer
try { try {
delete div.test; delete div.test;
} catch( e ) { } catch( e ) {
jQuery.support.deleteExpando = false; support.deleteExpando = false;
} }
if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
div.attachEvent( "onclick", function click() { div.attachEvent( "onclick", function click() {
// Cloning a node shouldn't copy over any // Cloning a node shouldn't copy over any
// bound event handlers (IE does this) // bound event handlers (IE does this)
jQuery.support.noCloneEvent = false; support.noCloneEvent = false;
div.detachEvent( "onclick", click ); div.detachEvent( "onclick", click );
}); });
div.cloneNode( true ).fireEvent( "onclick" ); div.cloneNode( true ).fireEvent( "onclick" );
} }
div = document.createElement("div");
div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>"; div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
var fragment = document.createDocumentFragment(); fragment = document.createDocumentFragment();
fragment.appendChild( div.firstChild ); fragment.appendChild( div.firstChild );
// WebKit doesn't clone checked state correctly in fragments // WebKit doesn't clone checked state correctly in fragments
jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
div.innerHTML = "";
// Figure out if the W3C box model works as expected // Figure out if the W3C box model works as expected
// document.body must exist before we can do this
jQuery(function() {
var div = document.createElement("div"),
body = document.getElementsByTagName("body")[0];
// Frameset documents with no body should not run this code
if ( !body ) {
return;
}
div.style.width = div.style.paddingLeft = "1px"; div.style.width = div.style.paddingLeft = "1px";
// We use our own, invisible, body
body = document.createElement( "body" );
bodyStyle = {
visibility: "hidden",
width: 0,
height: 0,
border: 0,
margin: 0
};
for ( i in bodyStyle ) {
body.style[ i ] = bodyStyle[ i ];
}
body.appendChild( div ); body.appendChild( div );
jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; document.documentElement.appendChild( body );
support.boxModel = div.offsetWidth === 2;
if ( "zoom" in div.style ) { if ( "zoom" in div.style ) {
// Check if natively block-level elements act like inline-block // Check if natively block-level elements act like inline-block
@ -162,17 +150,17 @@
// (IE < 8 does this) // (IE < 8 does this)
div.style.display = "inline"; div.style.display = "inline";
div.style.zoom = 1; div.style.zoom = 1;
jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2; support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
// Check if elements with layout shrink-wrap their children // Check if elements with layout shrink-wrap their children
// (IE 6 does this) // (IE 6 does this)
div.style.display = ""; div.style.display = "";
div.innerHTML = "<div style='width:4px;'></div>"; div.innerHTML = "<div style='width:4px;'></div>";
jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
} }
div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>"; div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
var tds = div.getElementsByTagName("td"); tds = div.getElementsByTagName( "td" );
// Check if table cells still have offsetWidth/Height when they are set // Check if table cells still have offsetWidth/Height when they are set
// to display:none and there are still other visible table cells in a // to display:none and there are still other visible table cells in a
@ -181,14 +169,14 @@
// display:none (it is still safe to use offsets if a parent element is // display:none (it is still safe to use offsets if a parent element is
// hidden; don safety goggles and see bug #4512 for more information). // hidden; don safety goggles and see bug #4512 for more information).
// (only IE 8 fails this test) // (only IE 8 fails this test)
jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0; isSupported = ( tds[ 0 ].offsetHeight === 0 );
tds[ 0 ].style.display = ""; tds[ 0 ].style.display = "";
tds[ 1 ].style.display = "none"; tds[ 1 ].style.display = "none";
// Check if empty table cells still have offsetWidth/Height // Check if empty table cells still have offsetWidth/Height
// (IE < 8 fail this test) // (IE < 8 fail this test)
jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
div.innerHTML = ""; div.innerHTML = "";
// Check if div with explicit width and no margin-right incorrectly // Check if div with explicit width and no margin-right incorrectly
@ -199,39 +187,42 @@
if ( document.defaultView && document.defaultView.getComputedStyle ) { if ( document.defaultView && document.defaultView.getComputedStyle ) {
div.style.width = "1px"; div.style.width = "1px";
div.style.marginRight = "0"; div.style.marginRight = "0";
jQuery.support.reliableMarginRight = ( parseInt(document.defaultView.getComputedStyle(div, null).marginRight, 10) || 0 ) === 0; support.reliableMarginRight =
( parseInt( document.defaultView.getComputedStyle(div).marginRight, 10 ) || 0 ) === 0;
} }
body.removeChild( div ).style.display = "none"; // Remove the body element we added
div = tds = null; document.documentElement.removeChild( body );
});
// Technique from Juriy Zaytsev // Technique from Juriy Zaytsev
// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
var eventSupported = function( eventName ) {
var el = document.createElement("div");
eventName = "on" + eventName;
// We only care about the case where non-standard event systems // We only care about the case where non-standard event systems
// are used, namely in IE. Short-circuiting here helps us to // are used, namely in IE. Short-circuiting here helps us to
// avoid an eval call (in setAttribute) which can cause CSP // avoid an eval call (in setAttribute) which can cause CSP
// to go haywire. See: https://developer.mozilla.org/en/Security/CSP // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
if ( !el.attachEvent ) { if ( div.attachEvent ) {
return true; for( i in {
} submit: 1,
change: 1,
var isSupported = (eventName in el); focusin: 1
} ) {
eventName = "on" + i;
isSupported = ( eventName in div );
if ( !isSupported ) { if ( !isSupported ) {
el.setAttribute(eventName, "return;"); div.setAttribute( eventName, "return;" );
isSupported = typeof el[eventName] === "function"; isSupported = ( typeof div[ eventName ] === "function" );
}
support[ i + "Bubbles" ] = isSupported;
}
} }
return isSupported;
};
jQuery.support.submitBubbles = eventSupported("submit");
jQuery.support.changeBubbles = eventSupported("change");
// release memory in IE // release memory in IE
div = all = a = null; body = div = all = a = tds = undefined;
return support;
})(); })();
// Keep track of boxModel
jQuery.boxModel = jQuery.support.boxModel;
})( jQuery ); })( jQuery );

View file

@ -1,14 +1,14 @@
// Simple script loader that uses jQuery.readyWait // Simple script loader that uses jQuery.readyWait via jQuery.holdReady()
//Hold on jQuery! //Hold on jQuery!
jQuery.readyWait++; jQuery.holdReady(true);
var readyRegExp = /^(complete|loaded)$/; var readyRegExp = /^(complete|loaded)$/;
function assetLoaded( evt ){ function assetLoaded( evt ){
var node = evt.currentTarget || evt.srcElement; var node = evt.currentTarget || evt.srcElement;
if ( evt.type === "load" || readyRegExp.test(node.readyState) ) { if ( evt.type === "load" || readyRegExp.test(node.readyState) ) {
jQuery.ready(true); jQuery.holdReady(false);
} }
} }

View file

@ -1,13 +1,13 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<!-- <!--
Test for jQuery.readyWait. Needs to be a Test for jQuery.holdReady. Needs to be a
standalone test since it deals with DOM standalone test since it deals with DOM
ready. ready.
--> -->
<head> <head>
<title> <title>
jQuery.readyWait Test jQuery.holdReady Test
</title> </title>
<style> <style>
div { margin-top: 10px; } div { margin-top: 10px; }
@ -52,15 +52,17 @@
</head> </head>
<body> <body>
<h1> <h1>
jQuery.readyWait Test jQuery.holdReady Test
</h1> </h1>
<p> <p>
This is a test page for jQuery.readyWait, that was This is a test page for jQuery.readyWait and jQuery.holdReady,
added due to this ticket see
<a href="http://bugs.jquery.com/ticket/6781">#6781</a>. <a href="http://bugs.jquery.com/ticket/6781">#6781</a>
and
<a href="http://bugs.jquery.com/ticket/8803">#8803</a>.
</p> </p>
<p> <p>
Test for jQuery.readyWait, which can be used Test for jQuery.holdReady, which can be used
by plugins and other scripts to indicate something by plugins and other scripts to indicate something
important to the page is still loading and needs important to the page is still loading and needs
to block the DOM ready callbacks that are registered to block the DOM ready callbacks that are registered
@ -68,7 +70,7 @@
</p> </p>
<p> <p>
Script loaders are the most likely kind of script Script loaders are the most likely kind of script
to use jQuery.readyWait, but it could be used by to use jQuery.holdReady, but it could be used by
other things like a script that loads a CSS file other things like a script that loads a CSS file
and wants to pause the DOM ready callbacks. and wants to pause the DOM ready callbacks.
</p> </p>

View file

@ -1600,7 +1600,7 @@ test("jQuery.ajax() - malformed JSON", function() {
}, },
error: function(xhr, msg, detailedMsg) { error: function(xhr, msg, detailedMsg) {
equals( "parsererror", msg, "A parse error occurred." ); equals( "parsererror", msg, "A parse error occurred." );
ok( /^Invalid JSON/.test(detailedMsg), "Detailed parsererror message provided" ); ok( /^(Invalid|SyntaxError|exception)/i.test(detailedMsg), "Detailed parsererror message provided" );
start(); start();
} }
}); });

View file

@ -12,7 +12,7 @@ test("Basic requirements", function() {
}); });
test("jQuery()", function() { test("jQuery()", function() {
expect(24); expect(25);
// Basic constructor's behavior // Basic constructor's behavior
@ -20,6 +20,7 @@ test("jQuery()", function() {
equals( jQuery(undefined).length, 0, "jQuery(undefined) === jQuery([])" ); equals( jQuery(undefined).length, 0, "jQuery(undefined) === jQuery([])" );
equals( jQuery(null).length, 0, "jQuery(null) === jQuery([])" ); equals( jQuery(null).length, 0, "jQuery(null) === jQuery([])" );
equals( jQuery("").length, 0, "jQuery('') === jQuery([])" ); equals( jQuery("").length, 0, "jQuery('') === jQuery([])" );
equals( jQuery("#").length, 0, "jQuery('#') === jQuery([])" );
var obj = jQuery("div"); var obj = jQuery("div");
equals( jQuery(obj).selector, "div", "jQuery(jQueryObj) == jQueryObj" ); equals( jQuery(obj).selector, "div", "jQuery(jQueryObj) == jQueryObj" );
@ -171,6 +172,26 @@ test("selector state", function() {
); );
}); });
test( "globalEval", function() {
expect( 3 );
jQuery.globalEval( "var globalEvalTest = true;" );
ok( window.globalEvalTest, "Test variable declarations are global" );
window.globalEvalTest = false;
jQuery.globalEval( "globalEvalTest = true;" );
ok( window.globalEvalTest, "Test variable assignments are global" );
window.globalEvalTest = false;
jQuery.globalEval( "this.globalEvalTest = true;" );
ok( window.globalEvalTest, "Test context (this) is the window object" );
window.globalEvalTest = undefined;
});
if ( !isLocal ) { if ( !isLocal ) {
test("browser", function() { test("browser", function() {
stop(); stop();
@ -468,7 +489,7 @@ test("isWindow", function() {
}); });
test("jQuery('html')", function() { test("jQuery('html')", function() {
expect(15); expect(18);
QUnit.reset(); QUnit.reset();
jQuery.foo = false; jQuery.foo = false;
@ -500,6 +521,19 @@ test("jQuery('html')", function() {
ok( jQuery("<div></div>")[0], "Create a div with closing tag." ); ok( jQuery("<div></div>")[0], "Create a div with closing tag." );
ok( jQuery("<table></table>")[0], "Create a table with closing tag." ); ok( jQuery("<table></table>")[0], "Create a table with closing tag." );
// Test very large html string #7990
var i;
var li = '<li>very large html string</li>';
var html = ['<ul>'];
for ( i = 0; i < 50000; i += 1 ) {
html.push(li);
}
html.push('</ul>');
html = jQuery(html.join(''))[0];
equals( html.nodeName.toUpperCase(), 'UL');
equals( html.firstChild.nodeName.toUpperCase(), 'LI');
equals( html.childNodes.length, 50000 );
}); });
test("jQuery('html', context)", function() { test("jQuery('html', context)", function() {

View file

@ -105,6 +105,38 @@ test("css(String|Hash)", function() {
equals( child[0].style.fontSize, old, "Make sure font-size isn't changed on null." ); equals( child[0].style.fontSize, old, "Make sure font-size isn't changed on null." );
}); });
test("css() explicit and relative values", function() {
expect(9);
var $elem = jQuery('#nothiddendiv');
$elem.css({ width: 1, height: 1 });
equals( $elem.width(), 1, "Initial css set or width/height works (hash)" );
$elem.css({ width: "+=9" });
equals( $elem.width(), 10, "'+=9' on width (hash)" );
$elem.css({ width: "-=9" });
equals( $elem.width(), 1, "'-=9' on width (hash)" );
$elem.css({ width: "+=9px" });
equals( $elem.width(), 10, "'+=9px' on width (hash)" );
$elem.css({ width: "-=9px" });
equals( $elem.width(), 1, "'-=9px' on width (hash)" );
$elem.css( "width", "+=9" );
equals( $elem.width(), 10, "'+=9' on width (params)" );
$elem.css( "width", "-=9" ) ;
equals( $elem.width(), 1, "'-=9' on width (params)" );
$elem.css( "width", "+=9px" );
equals( $elem.width(), 10, "'+=9px' on width (params)" );
$elem.css( "width", "-=9px" );
equals( $elem.width(), 1, "'-=9px' on width (params)" );
});
test("css(String, Object)", function() { test("css(String, Object)", function() {
expect(22); expect(22);

View file

@ -486,3 +486,20 @@ if (window.JSON && window.JSON.stringify) {
equals( JSON.stringify(obj), '{"foo":"bar"}', "Expando is hidden from JSON.stringify" ); equals( JSON.stringify(obj), '{"foo":"bar"}', "Expando is hidden from JSON.stringify" );
}); });
} }
test("jQuery.data should follow html5 specification regarding camel casing", function() {
expect(6);
var div = jQuery("<div id='myObject' data-foo='a' data-foo-bar='b' data-foo-bar-baz='c'></div>")
.prependTo("body");
equals(div.data().foo, "a", "Verify single word data-* key");
equals(div.data().fooBar, "b", "Verify multiple word data-* key");
equals(div.data().fooBarBaz, "c", "Verify multiple word data-* key");
equals(div.data("foo"), "a", "Verify single word data-* key");
equals(div.data("fooBar"), "b", "Verify multiple word data-* key");
equals(div.data("fooBarBaz"), "c", "Verify multiple word data-* key");
div.remove();
});

View file

@ -1,6 +1,12 @@
module("deferred", { teardown: moduleTeardown }); module("deferred", { teardown: moduleTeardown });
test("jQuery._Deferred()", function() { jQuery.each( [ "", " - new operator" ], function( _, withNew ) {
function createDeferred() {
return withNew ? new jQuery._Deferred() : jQuery._Deferred();
}
test("jQuery._Deferred" + withNew, function() {
expect( 11 ); expect( 11 );
@ -8,7 +14,7 @@ test("jQuery._Deferred()", function() {
object, object,
test; test;
deferred = jQuery._Deferred(); deferred = createDeferred();
test = false; test = false;
@ -41,7 +47,7 @@ test("jQuery._Deferred()", function() {
ok( test , "Test cancel" ); ok( test , "Test cancel" );
deferred = jQuery._Deferred().resolve(); deferred = createDeferred().resolve();
try { try {
deferred.done( function() { deferred.done( function() {
@ -55,7 +61,7 @@ test("jQuery._Deferred()", function() {
} }
test = ""; test = "";
deferred = jQuery._Deferred().done( function() { deferred = createDeferred().done( function() {
test += "A"; test += "A";
@ -86,68 +92,182 @@ test("jQuery._Deferred()", function() {
strictEqual( test , "ABC" , "Test done callbacks order" ); strictEqual( test , "ABC" , "Test done callbacks order" );
deferred = jQuery._Deferred(); deferred = createDeferred();
deferred.resolveWith( jQuery , [ document ] ).done( function( doc ) { deferred.resolveWith( jQuery , [ document ] ).done( function( doc ) {
ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" ); ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" );
}); });
// #8421 // #8421
deferred = jQuery._Deferred(); deferred = createDeferred();
deferred.resolveWith().done(function() { deferred.resolveWith().done(function() {
ok( true, "Test resolveWith can be called with no argument" ); ok( true, "Test resolveWith can be called with no argument" );
}); });
}); });
} );
test("jQuery.Deferred()", function() { jQuery.each( [ "", " - new operator" ], function( _, withNew ) {
expect( 10 ); function createDeferred( fn ) {
return withNew ? new jQuery.Deferred( fn ) : jQuery.Deferred( fn );
}
jQuery.Deferred( function( defer ) { test("jQuery.Deferred" + withNew, function() {
strictEqual( this , defer , "Defer passed as this & first argument" );
expect( 8 );
createDeferred().resolve().then( function() {
ok( true , "Success on resolve" );
ok( this.isResolved(), "Deferred is resolved" );
}, function() {
ok( false , "Error on resolve" );
}).always( function() {
ok( true , "Always callback on resolve" );
});
createDeferred().reject().then( function() {
ok( false , "Success on reject" );
}, function() {
ok( true , "Error on reject" );
ok( this.isRejected(), "Deferred is rejected" );
}).always( function() {
ok( true , "Always callback on reject" );
});
createDeferred( function( defer ) {
ok( this === defer , "Defer passed as this & first argument" );
this.resolve( "done" ); this.resolve( "done" );
}).then( function( value ) { }).then( function( value ) {
strictEqual( value , "done" , "Passed function executed" ); strictEqual( value , "done" , "Passed function executed" );
}); });
});
jQuery.Deferred().resolve().then( function() {
ok( true , "Success on resolve" );
}, function() {
ok( false , "Error on resolve" );
} ); } );
jQuery.Deferred().reject().then( function() { test( "jQuery.Deferred.pipe - filtering (done)", function() {
ok( false , "Success on reject" );
}, function() { expect(3);
ok( true , "Error on reject" );
var defer = jQuery.Deferred(),
piped = defer.pipe(function( a, b ) {
return a * b;
}),
value1,
value2,
value3;
piped.done(function( result ) {
value3 = result;
}); });
( new jQuery.Deferred( function( defer ) { defer.done(function( a, b ) {
strictEqual( this , defer , "Defer passed as this & first argument (new)" ); value1 = a;
this.resolve( "done" ); value2 = b;
}) ).then( function( value ) {
strictEqual( value , "done" , "Passed function executed (new)" );
}); });
( new jQuery.Deferred() ).resolve().then( function() { defer.resolve( 2, 3 );
ok( true , "Success on resolve (new)" );
}, function() { strictEqual( value1, 2, "first resolve value ok" );
ok( false , "Error on resolve (new)" ); strictEqual( value2, 3, "second resolve value ok" );
strictEqual( value3, 6, "result of filter ok" );
jQuery.Deferred().reject().pipe(function() {
ok( false, "pipe should not be called on reject" );
});
}); });
( new jQuery.Deferred() ).reject().then( function() { test( "jQuery.Deferred.pipe - filtering (fail)", function() {
ok( false , "Success on reject (new)" );
}, function() { expect(3);
ok( true , "Error on reject (new)" );
var defer = jQuery.Deferred(),
piped = defer.pipe( null, function( a, b ) {
return a * b;
} ),
value1,
value2,
value3;
piped.fail(function( result ) {
value3 = result;
}); });
var tmp = jQuery.Deferred(); defer.fail(function( a, b ) {
value1 = a;
strictEqual( tmp.promise() , tmp.promise() , "Test deferred always return same promise" ); value2 = b;
strictEqual( tmp.promise() , tmp.promise().promise() , "Test deferred's promise always return same promise as deferred" );
}); });
test("jQuery.when()", function() { defer.reject( 2, 3 );
strictEqual( value1, 2, "first reject value ok" );
strictEqual( value2, 3, "second reject value ok" );
strictEqual( value3, 6, "result of filter ok" );
jQuery.Deferred().resolve().pipe( null, function() {
ok( false, "pipe should not be called on resolve" );
} );
});
test( "jQuery.Deferred.pipe - deferred (done)", function() {
expect(3);
var defer = jQuery.Deferred(),
piped = defer.pipe(function( a, b ) {
return jQuery.Deferred(function( defer ) {
defer.reject( a * b );
});
}),
value1,
value2,
value3;
piped.fail(function( result ) {
value3 = result;
});
defer.done(function( a, b ) {
value1 = a;
value2 = b;
});
defer.resolve( 2, 3 );
strictEqual( value1, 2, "first resolve value ok" );
strictEqual( value2, 3, "second resolve value ok" );
strictEqual( value3, 6, "result of filter ok" );
});
test( "jQuery.Deferred.pipe - deferred (fail)", function() {
expect(3);
var defer = jQuery.Deferred(),
piped = defer.pipe( null, function( a, b ) {
return jQuery.Deferred(function( defer ) {
defer.resolve( a * b );
});
} ),
value1,
value2,
value3;
piped.done(function( result ) {
value3 = result;
});
defer.fail(function( a, b ) {
value1 = a;
value2 = b;
});
defer.reject( 2, 3 );
strictEqual( value1, 2, "first reject value ok" );
strictEqual( value2, 3, "second reject value ok" );
strictEqual( value3, 6, "result of filter ok" );
});
test( "jQuery.when" , function() {
expect( 23 ); expect( 23 );
@ -166,13 +286,13 @@ test("jQuery.when()", function() {
} , function( message , value ) { } , function( message , value ) {
ok( jQuery.isFunction( jQuery.when( value ).then( function( resolveValue ) { ok( jQuery.isFunction( jQuery.when( value ).done(function( resolveValue ) {
strictEqual( resolveValue , value , "Test the promise was resolved with " + message ); strictEqual( resolveValue , value , "Test the promise was resolved with " + message );
}).promise ) , "Test " + message + " triggers the creation of a new Promise" ); }).promise ) , "Test " + message + " triggers the creation of a new Promise" );
} ); } );
ok( jQuery.isFunction( jQuery.when().then( function( resolveValue ) { ok( jQuery.isFunction( jQuery.when().done(function( resolveValue ) {
strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" ); strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" );
}).promise ) , "Test calling when with no parameter triggers the creation of a new Promise" ); }).promise ) , "Test calling when with no parameter triggers the creation of a new Promise" );
@ -181,42 +301,48 @@ test("jQuery.when()", function() {
for( i = 1 ; i < 4 ; i++ ) { for( i = 1 ; i < 4 ; i++ ) {
jQuery.when( cache || jQuery.Deferred( function() { jQuery.when( cache || jQuery.Deferred( function() {
this.resolve( i ); this.resolve( i );
}) ).then( function( value ) { }) ).done(function( value ) {
strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) ); strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) );
cache = value; cache = value;
}, function() {
ok( false , "Fail called" );
}); });
} }
}); });
test("jQuery.when() - joined", function() { test("jQuery.when - joined", function() {
expect(8); expect(25);
jQuery.when( 1, 2, 3 ).done( function( a, b, c ) { var deferreds = {
strictEqual( a , 1 , "Test first param is first resolved value - non-observables" ); value: 1,
strictEqual( b , 2 , "Test second param is second resolved value - non-observables" ); success: jQuery.Deferred().resolve( 1 ),
strictEqual( c , 3 , "Test third param is third resolved value - non-observables" ); error: jQuery.Deferred().reject( 0 ),
}).fail( function() { futureSuccess: jQuery.Deferred(),
ok( false , "Test the created deferred was resolved - non-observables"); futureError: jQuery.Deferred()
}); },
willSucceed = {
value: true,
success: true,
error: false,
futureSuccess: true,
futureError: false
};
var successDeferred = jQuery.Deferred().resolve( 1 , 2 , 3 ), jQuery.each( deferreds, function( id1, defer1 ) {
errorDeferred = jQuery.Deferred().reject( "error" , "errorParam" ); jQuery.each( deferreds, function( id2, defer2 ) {
var shouldResolve = willSucceed[ id1 ] && willSucceed[ id2 ],
jQuery.when( 1 , successDeferred , 3 ).done( function( a, b, c ) { expected = shouldResolve ? [ 1, 1 ] : [ 0, undefined ],
strictEqual( a , 1 , "Test first param is first resolved value - resolved observable" ); code = id1 + "/" + id2;
same( b , [ 1 , 2 , 3 ] , "Test second param is second resolved value - resolved observable" ); jQuery.when( defer1, defer2 ).done(function( a, b ) {
strictEqual( c , 3 , "Test third param is third resolved value - resolved observable" ); if ( shouldResolve ) {
}).fail( function() { same( [ a, b ], expected, code + " => resolve" );
ok( false , "Test the created deferred was resolved - resolved observable"); }
}); }).fail(function( a, b ) {
if ( !shouldResolve ) {
jQuery.when( 1 , errorDeferred , 3 ).done( function() { same( [ a, b ], expected, code + " => resolve" );
ok( false , "Test the created deferred was rejected - rejected observable"); }
}).fail( function( error , errorParam ) {
strictEqual( error , "error" , "Test first param is first rejected value - rejected observable" );
strictEqual( errorParam , "errorParam" , "Test second param is second rejected value - rejected observable" );
}); });
} ); } );
} );
deferreds.futureSuccess.resolve( 1 );
deferreds.futureError.reject( 0 );
});

41
test/unit/effects.js vendored
View file

@ -717,59 +717,64 @@ jQuery.each( {
var anim = { width: t_w, height: t_h, opacity: t_o }; var anim = { width: t_w, height: t_h, opacity: t_o };
elem.animate(anim, 50, function(){ elem.animate(anim, 50);
jQuery.when( elem ).done(function( elem ){
elem = elem[ 0 ];
if ( t_w == "show" ) if ( t_w == "show" )
equals( this.style.display, "block", "Showing, display should block: " + this.style.display); equals( elem.style.display, "block", "Showing, display should block: " + elem.style.display);
if ( t_w == "hide"||t_w == "show" ) if ( t_w == "hide"||t_w == "show" )
ok(f_w === "" ? this.style.width === f_w : this.style.width.indexOf(f_w) === 0, "Width must be reset to " + f_w + ": " + this.style.width); ok(f_w === "" ? elem.style.width === f_w : elem.style.width.indexOf(f_w) === 0, "Width must be reset to " + f_w + ": " + elem.style.width);
if ( t_h == "hide"||t_h == "show" ) if ( t_h == "hide"||t_h == "show" )
ok(f_h === "" ? this.style.height === f_h : this.style.height.indexOf(f_h) === 0, "Height must be reset to " + f_h + ": " + this.style.height); ok(f_h === "" ? elem.style.height === f_h : elem.style.height.indexOf(f_h) === 0, "Height must be reset to " + f_h + ": " + elem.style.height);
var cur_o = jQuery.style(this, "opacity"); var cur_o = jQuery.style(elem, "opacity");
if ( t_o == "hide" || t_o == "show" ) if ( t_o == "hide" || t_o == "show" )
equals(cur_o, f_o, "Opacity must be reset to " + f_o + ": " + cur_o); equals(cur_o, f_o, "Opacity must be reset to " + f_o + ": " + cur_o);
if ( t_w == "hide" ) if ( t_w == "hide" )
equals(this.style.display, "none", "Hiding, display should be none: " + this.style.display); equals(elem.style.display, "none", "Hiding, display should be none: " + elem.style.display);
if ( t_o.constructor == Number ) { if ( t_o.constructor == Number ) {
equals(cur_o, t_o, "Final opacity should be " + t_o + ": " + cur_o); equals(cur_o, t_o, "Final opacity should be " + t_o + ": " + cur_o);
ok(jQuery.css(this, "opacity") != "" || cur_o == t_o, "Opacity should be explicitly set to " + t_o + ", is instead: " + cur_o); ok(jQuery.css(elem, "opacity") != "" || cur_o == t_o, "Opacity should be explicitly set to " + t_o + ", is instead: " + cur_o);
} }
if ( t_w.constructor == Number ) { if ( t_w.constructor == Number ) {
equals(this.style.width, t_w + "px", "Final width should be " + t_w + ": " + this.style.width); equals(elem.style.width, t_w + "px", "Final width should be " + t_w + ": " + elem.style.width);
var cur_w = jQuery.css(this,"width"); var cur_w = jQuery.css(elem,"width");
ok(this.style.width != "" || cur_w == t_w, "Width should be explicitly set to " + t_w + ", is instead: " + cur_w); ok(elem.style.width != "" || cur_w == t_w, "Width should be explicitly set to " + t_w + ", is instead: " + cur_w);
} }
if ( t_h.constructor == Number ) { if ( t_h.constructor == Number ) {
equals(this.style.height, t_h + "px", "Final height should be " + t_h + ": " + this.style.height); equals(elem.style.height, t_h + "px", "Final height should be " + t_h + ": " + elem.style.height);
var cur_h = jQuery.css(this,"height"); var cur_h = jQuery.css(elem,"height");
ok(this.style.height != "" || cur_h == t_h, "Height should be explicitly set to " + t_h + ", is instead: " + cur_w); ok(elem.style.height != "" || cur_h == t_h, "Height should be explicitly set to " + t_h + ", is instead: " + cur_w);
} }
if ( t_h == "show" ) { if ( t_h == "show" ) {
var old_h = jQuery.css(this, "height"); var old_h = jQuery.css(elem, "height");
jQuery(this).append("<br/>Some more text<br/>and some more..."); jQuery(elem).append("<br/>Some more text<br/>and some more...");
if ( /Auto/.test( fn ) ) { if ( /Auto/.test( fn ) ) {
notEqual(jQuery.css(this, "height"), old_h, "Make sure height is auto."); notEqual(jQuery.css(elem, "height"), old_h, "Make sure height is auto.");
} else { } else {
equals(jQuery.css(this, "height"), old_h, "Make sure height is not auto."); equals(jQuery.css(elem, "height"), old_h, "Make sure height is not auto.");
} }
} }
// manually remove generated element // manually remove generated element
jQuery(this).remove(); jQuery(elem).remove();
start(); start();
}); });

View file

@ -550,6 +550,47 @@ test("bind(name, false), unbind(name, false)", function() {
jQuery("#main").unbind("click"); jQuery("#main").unbind("click");
}); });
test("live(name, false), die(name, false)", function() {
expect(3);
var main = 0;
jQuery("#main").live("click", function(e){ main++; });
jQuery("#ap").trigger("click");
equals( main, 1, "Verify that the trigger happened correctly." );
main = 0;
jQuery("#ap").live("click", false);
jQuery("#ap").trigger("click");
equals( main, 0, "Verify that no bubble happened." );
main = 0;
jQuery("#ap").die("click", false);
jQuery("#ap").trigger("click");
equals( main, 1, "Verify that the trigger happened correctly." );
jQuery("#main").die("click");
});
test("delegate(selector, name, false), undelegate(selector, name, false)", function() {
expect(3);
var main = 0;
jQuery("#main").delegate("#ap", "click", function(e){ main++; });
jQuery("#ap").trigger("click");
equals( main, 1, "Verify that the trigger happened correctly." );
main = 0;
jQuery("#ap").delegate("#groups", "click", false);
jQuery("#groups").trigger("click");
equals( main, 0, "Verify that no bubble happened." );
main = 0;
jQuery("#ap").undelegate("#groups", "click", false);
jQuery("#groups").trigger("click");
equals( main, 1, "Verify that the trigger happened correctly." );
jQuery("#main").undelegate("#ap", "click");
});
test("bind()/trigger()/unbind() on plain object", function() { test("bind()/trigger()/unbind() on plain object", function() {
expect( 7 ); expect( 7 );
@ -738,10 +779,11 @@ test("trigger() shortcuts", function() {
}); });
test("trigger() bubbling", function() { test("trigger() bubbling", function() {
expect(14); expect(17);
var doc = 0, html = 0, body = 0, main = 0, ap = 0; var win = 0, doc = 0, html = 0, body = 0, main = 0, ap = 0;
jQuery(window).bind("click", function(e){ win++; });
jQuery(document).bind("click", function(e){ if ( e.target !== document) { doc++; } }); jQuery(document).bind("click", function(e){ if ( e.target !== document) { doc++; } });
jQuery("html").bind("click", function(e){ html++; }); jQuery("html").bind("click", function(e){ html++; });
jQuery("body").bind("click", function(e){ body++; }); jQuery("body").bind("click", function(e){ body++; });
@ -749,15 +791,18 @@ test("trigger() bubbling", function() {
jQuery("#ap").bind("click", function(){ ap++; return false; }); jQuery("#ap").bind("click", function(){ ap++; return false; });
jQuery("html").trigger("click"); jQuery("html").trigger("click");
equals( win, 1, "HTML bubble" );
equals( doc, 1, "HTML bubble" ); equals( doc, 1, "HTML bubble" );
equals( html, 1, "HTML bubble" ); equals( html, 1, "HTML bubble" );
jQuery("body").trigger("click"); jQuery("body").trigger("click");
equals( win, 2, "Body bubble" );
equals( doc, 2, "Body bubble" ); equals( doc, 2, "Body bubble" );
equals( html, 2, "Body bubble" ); equals( html, 2, "Body bubble" );
equals( body, 1, "Body bubble" ); equals( body, 1, "Body bubble" );
jQuery("#main").trigger("click"); jQuery("#main").trigger("click");
equals( win, 3, "Main bubble" );
equals( doc, 3, "Main bubble" ); equals( doc, 3, "Main bubble" );
equals( html, 3, "Main bubble" ); equals( html, 3, "Main bubble" );
equals( body, 2, "Main bubble" ); equals( body, 2, "Main bubble" );
@ -2010,15 +2055,94 @@ test("focusin bubbles", function() {
jQuery( "body" ).unbind( "focusin.focusinBubblesTest" ); jQuery( "body" ).unbind( "focusin.focusinBubblesTest" );
}); });
/* test("custom events with colons (#3533, #8272)", function() {
test("jQuery(function($) {})", function() { expect(1);
stop();
jQuery(function($) { var tab = jQuery("<table><tr><td>trigger</td></tr></table>").appendTo("body");
equals(jQuery, $, "ready doesn't provide an event object, instead it provides a reference to the jQuery function, see http://docs.jquery.com/Events/ready#fn"); try {
start(); tab.trigger("back:forth");
}); ok( true, "colon events don't throw" );
} catch ( e ) {
ok( false, "colon events die" );
};
tab.remove();
}); });
(function(){
// This code must be run before DOM ready!
var notYetReady, noEarlyExecution,
order = [],
args = {};
notYetReady = !jQuery.isReady;
test("jQuery.isReady", function() {
expect(2);
equals(notYetReady, true, "jQuery.isReady should not be true before DOM ready");
equals(jQuery.isReady, true, "jQuery.isReady should be true once DOM is ready");
});
// Create an event handler.
function makeHandler( testId ) {
// When returned function is executed, push testId onto `order` array
// to ensure execution order. Also, store event handler arg to ensure
// the correct arg is being passed into the event handler.
return function( arg ) {
order.push(testId);
args[testId] = arg;
};
}
// Bind to the ready event in every possible way.
jQuery(makeHandler("a"));
jQuery(document).ready(makeHandler("b"));
jQuery(document).bind("ready.readytest", makeHandler("c"));
// Do it twice, just to be sure.
jQuery(makeHandler("d"));
jQuery(document).ready(makeHandler("e"));
jQuery(document).bind("ready.readytest", makeHandler("f"));
noEarlyExecution = order.length == 0;
// This assumes that QUnit tests are run on DOM ready!
test("jQuery ready", function() {
expect(10);
ok(noEarlyExecution, "Handlers bound to DOM ready should not execute before DOM ready");
// Ensure execution order.
same(order, ["a", "b", "d", "e", "c", "f"], "Bound DOM ready handlers should execute in bind-order, but those bound with jQuery(document).bind( 'ready', fn ) will always execute last");
// Ensure handler argument is correct.
equals(args.a, jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery");
equals(args.b, jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery");
ok(args.c instanceof jQuery.Event, "Argument passed to fn in jQuery(document).bind( 'ready', fn ) should be an event object");
order = [];
// Now that the ready event has fired, again bind to the ready event
// in every possible way. These event handlers should execute immediately.
jQuery(makeHandler("g"));
equals(order.pop(), "g", "Event handler should execute immediately");
equals(args.g, jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery");
jQuery(document).ready(makeHandler("h"));
equals(order.pop(), "h", "Event handler should execute immediately");
equals(args.h, jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery");
jQuery(document).bind("ready.readytest", makeHandler("never"));
equals(order.length, 0, "Event handler should never execute since DOM ready has already passed");
// Cleanup.
jQuery(document).unbind("ready.readytest");
});
})();
/*
test("event properties", function() { test("event properties", function() {
stop(); stop();
jQuery("#simon1").click(function(event) { jQuery("#simon1").click(function(event) {