+ // Getting an attribute
+ return length ? fn( elems[0], key ) : undefined;
+ },
+
+ now: function() {
+ return (new Date()).getTime();
+ },
+
+ // Create a simple deferred (one callbacks list)
+ _Deferred: function() {
+
+ var // callbacks list
+ callbacks = [],
+ // stored [ context , args ]
+ fired,
+ // to avoid firing when already doing so
+ firing,
+ // flag to know if the deferred has been cancelled
+ cancelled,
+ // the deferred itself
+ deferred = {
+
+ // then( f1, f2, ...)
+ then: function () {
+
+ if ( ! cancelled ) {
+
+ var args = arguments,
+ i,
+ length,
+ elem,
+ type,
+ _fired;
+
+ if ( fired ) {
+ _fired = fired;
+ fired = 0;
+ }
+
+ for ( i = 0, length = args.length ; i < length ; i++ ) {
+ elem = args[ i ];
+ type = jQuery.type( elem );
+ if ( type === "array" ) {
+ deferred.then.apply( deferred , elem );
+ } else if ( type === "function" ) {
+ callbacks.push( elem );
+ }
+ }
+
+ if ( _fired ) {
+ deferred.fire( _fired[ 0 ] , _fired[ 1 ] );
+ }
+ }
+
+ return this;
+ },
+
+ // resolve with given context and args
+ fire: function( context , args ) {
+ if ( ! cancelled && ! fired && ! firing ) {
+
+ firing = 1;
+
+ try {
+ while( callbacks[ 0 ] ) {
+ callbacks.shift().apply( context , args );
+ }
+ }
+ finally {
+ fired = [ context , args ];
+ firing = 0;
+ }
+ }
+ return this;
+ },
+
+ // resolve with this as context and given arguments
+ resolve: function() {
+ deferred.fire( jQuery.isFunction( this.promise ) ? this.promise() : this , arguments );
+ return this;
+ },
+
+ // Has this deferred been resolved?
+ isResolved: function() {
+ return !!( firing || fired );
+ },
+
+ // Cancel
+ cancel: function() {
+ cancelled = 1;
+ callbacks = [];
+ return this;
+ }
+ };
+
+ return deferred;
+ },
+
+ // Full fledged deferred (two callbacks list)
+ // Typical success/error system
+ Deferred: function( func ) {
+
+ var deferred = jQuery._Deferred(),
+ failDeferred = jQuery._Deferred();