Commit c10a76ec authored by timmywil's avatar timmywil

Merge branch 'master' into attrhooks.1.6v2

parents da89d876 7fb95ebe
...@@ -56,6 +56,89 @@ Sometimes, the various git repositories get into an inconsistent state where bui ...@@ -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?
---------- ----------
......
...@@ -248,7 +248,7 @@ jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".sp ...@@ -248,7 +248,7 @@ jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".sp
jQuery.fn[ o ] = function( f ){ jQuery.fn[ o ] = function( f ){
return this.bind( o, f ); return this.bind( o, f );
}; };
} ); });
jQuery.each( [ "get", "post" ], function( i, method ) { jQuery.each( [ "get", "post" ], function( i, method ) {
jQuery[ method ] = function( url, data, callback, type ) { jQuery[ method ] = function( url, data, callback, type ) {
...@@ -267,7 +267,7 @@ jQuery.each( [ "get", "post" ], function( i, method ) { ...@@ -267,7 +267,7 @@ jQuery.each( [ "get", "post" ], function( i, method ) {
dataType: type dataType: type
}); });
}; };
} ); });
jQuery.extend({ jQuery.extend({
...@@ -757,7 +757,7 @@ jQuery.extend({ ...@@ -757,7 +757,7 @@ jQuery.extend({
// Serialize the form elements // Serialize the form elements
jQuery.each( a, function() { jQuery.each( a, function() {
add( this.name, this.value ); add( this.name, this.value );
} ); });
} else { } else {
// If traditional, encode the "old" way (the way 1.3.2 or older // If traditional, encode the "old" way (the way 1.3.2 or older
......
...@@ -76,6 +76,6 @@ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { ...@@ -76,6 +76,6 @@ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
// Delegate to script // Delegate to script
return "script"; return "script";
} }
} ); });
})( jQuery ); })( jQuery );
...@@ -25,7 +25,7 @@ jQuery.ajaxPrefilter( "script", function( s ) { ...@@ -25,7 +25,7 @@ jQuery.ajaxPrefilter( "script", function( s ) {
s.type = "GET"; s.type = "GET";
s.global = false; s.global = false;
} }
} ); });
// Bind script tag hack transport // Bind script tag hack transport
jQuery.ajaxTransport( "script", function(s) { jQuery.ajaxTransport( "script", function(s) {
...@@ -53,7 +53,7 @@ jQuery.ajaxTransport( "script", function(s) { ...@@ -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;
...@@ -84,6 +84,6 @@ jQuery.ajaxTransport( "script", function(s) { ...@@ -84,6 +84,6 @@ jQuery.ajaxTransport( "script", function(s) {
} }
}; };
} }
} ); });
})( jQuery ); })( jQuery );
...@@ -34,6 +34,20 @@ jQuery.fn.extend({ ...@@ -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) {
......
...@@ -17,7 +17,7 @@ var jQuery = function( selector, context ) { ...@@ -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 = { ...@@ -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({ ...@@ -369,15 +374,19 @@ jQuery.extend({
// the ready event fires. See #6781 // the ready event fires. See #6781
readyWait: 1, readyWait: 1,
// Handle when the DOM is ready // Hold (or release) the ready event
ready: function( wait ) { holdReady: function( hold ) {
// A third-party is pushing the ready event forwards if ( hold ) {
if ( wait === true ) { jQuery.readyWait++;
jQuery.readyWait--; } else {
jQuery.ready( true );
} }
},
// Make sure that the DOM is not already loaded // Handle when the DOM is ready
if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { ready: function( wait ) {
// Either a released hold or an DOMready/load event and not yet ready
if ( (wait === true && !--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({ ...@@ -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({ ...@@ -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({ ...@@ -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 ) { ...@@ -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]+/;
......
...@@ -7,6 +7,8 @@ var ralpha = /alpha\([^)]*\)/i, ...@@ -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({ ...@@ -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";
} }
......
(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({ ...@@ -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 ) { ...@@ -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 {
......
(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({ ...@@ -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 ) {
...@@ -119,7 +146,7 @@ jQuery.extend({ ...@@ -119,7 +146,7 @@ jQuery.extend({
} }
return obj; return obj;
} }
} ); });
// Make sure only one callback list will be used // Make sure only one callback list will be used
deferred.done( failDeferred.cancel ).fail( deferred.cancel ); deferred.done( failDeferred.cancel ).fail( deferred.cancel );
// Unexpose cancel // Unexpose cancel
......
...@@ -11,7 +11,17 @@ var elemdisplay = {}, ...@@ -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 = { ...@@ -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 = { ...@@ -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;
...@@ -417,7 +428,7 @@ jQuery.fx.prototype = { ...@@ -417,7 +428,7 @@ jQuery.fx.prototype = {
jQuery.each( [ "", "X", "Y" ], function (index, value) { jQuery.each( [ "", "X", "Y" ], function (index, value) {
elem.style[ "overflow" + value ] = options.overflow[index]; elem.style[ "overflow" + value ] = options.overflow[index];
} ); });
} }
// Hide the element if the "hide" operation was done // Hide the element if the "hide" operation was done
......
...@@ -71,8 +71,8 @@ jQuery.event = { ...@@ -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 = { ...@@ -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 = { ...@@ -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 = { ...@@ -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 = { ...@@ -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
} catch (inlineError) {}
if ( !event.isPropagationStopped() && parent ) { // Bubble up to document, then to window
jQuery.event.trigger( event, data, parent, true ); cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;
} while ( cur && !event.isPropagationStopped() );
} else if ( !event.isDefaultPrevented() ) { // If nobody prevented the default action, do it now
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 = { ...@@ -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 = { ...@@ -450,8 +435,6 @@ jQuery.event = {
} }
} }
} }
}
return event.result; return event.result;
}, },
...@@ -490,8 +473,9 @@ jQuery.event = { ...@@ -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 ) { ...@@ -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 ) { ...@@ -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;
} }
......
...@@ -28,7 +28,8 @@ jQuery.extend({ ...@@ -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({ ...@@ -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({ ...@@ -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();
} }
}); });
......
Subproject commit f12b9309269ba7e705a99efe099f86ed1fe98d58 Subproject commit 80f2b81d1fbc13d62afb91cb87e1452fbbec1ef4
This diff is collapsed.
// 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);
} }
} }
......
<!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 @@ ...@@ -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 @@ ...@@ -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>
......
...@@ -1600,7 +1600,7 @@ test("jQuery.ajax() - malformed JSON", function() { ...@@ -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();
} }
}); });
......
...@@ -12,7 +12,7 @@ test("Basic requirements", function() { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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() {
......
...@@ -105,6 +105,38 @@ test("css(String|Hash)", function() { ...@@ -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);
......
...@@ -486,3 +486,20 @@ if (window.JSON && window.JSON.stringify) { ...@@ -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();
});
\ No newline at end of file
This diff is collapsed.
...@@ -717,59 +717,64 @@ jQuery.each( { ...@@ -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();
}); });
......
...@@ -550,6 +550,47 @@ test("bind(name, false), unbind(name, false)", function() { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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) {
......
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