r89853 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r89852‎ | r89853 | r89854 >
Date:22:15, 10 June 2011
Author:krinkle
Status:resolved (Comments)
Tags:
Comment:
Added jquery.qunit.completenessTest.js (A jQuery/QUnit test coverage utility)
* Added to /resources
* Conditionally loaded (condition being that the url parameter "completenesstest" has a truthy value)
* Fixed a test that was using === and true
* Setting an added method somewhere back to undefined so it won't be listed as a potential "missing test".
Modified paths:
  • /trunk/phase3/resources/jquery/jquery.js (modified) (history)
  • /trunk/phase3/resources/jquery/jquery.qunit.completenessTest.js (added) (history)
  • /trunk/phase3/tests/qunit/index.html (modified) (history)
  • /trunk/phase3/tests/qunit/jquery.qunit.completenessTest.config.js (added) (history)
  • /trunk/phase3/tests/qunit/suites/resources/mediawiki/mediawiki.js (modified) (history)

Diff [purge]

Index: trunk/phase3/tests/qunit/index.html
@@ -57,6 +57,14 @@
5858 the following script will allow it to extract the results.
5959 Harmless otherwise. -->
6060 <script src="testswarm.inject.js"></script>
 61+
 62+ <!-- CompletenessTest -->
 63+ <script>
 64+ if ( QUnit.urlParams.completenesstest ) {
 65+ document.write( '\x3Cscript src="../../resources/jquery/jquery.qunit.completenessTest.js">\x3C/script>' );
 66+ document.write( '\x3Cscript src="jquery.qunit.completenessTest.config.js">\x3C/script>' );
 67+ }
 68+ </script>
6169 </head>
6270 <body>
6371 <h1 id="qunit-header">MediaWiki JavaScript Test Suite</h1>
Index: trunk/phase3/tests/qunit/suites/resources/mediawiki/mediawiki.js
@@ -16,7 +16,6 @@
1717
1818 test( 'mw.Map', function() {
1919 expect(15);
20 -
2120 ok( mw.Map, 'mw.Map defined' );
2221
2322 var conf = new mw.Map(),
@@ -49,7 +48,7 @@
5049
5150 strictEqual( conf.exists( 'foo' ), true, 'Map.exists returns boolean true if a key exists' );
5251 strictEqual( conf.exists( 'notExist' ), false, 'Map.exists returns boolean false if a key does not exists' );
53 - strictEqual( conf.get() === conf.values, true, 'Map.get returns the entire values object by reference (if called without arguments)' );
 52+ strictEqual( conf.get(), conf.values, 'Map.get returns the entire values object by reference (if called without arguments)' );
5453
5554 conf.set( 'globalMapChecker', 'Hi' );
5655
@@ -107,7 +106,6 @@
108107 strictEqual( goodbye.exists(), false, 'Message.exists returns false for inexisting messages' );
109108
110109 equal( goodbye.toString(), '<goodbye>', 'Message.toString returns <key> if key does not exist' );
111 -
112110 });
113111
114112 test( 'mw.msg', function() {
@@ -160,6 +158,7 @@
161159 // /sample/awesome.js declares the "mw.loader.testCallback" function
162160 // which contains a call to start() and ok()
163161 mw.loader.testCallback();
 162+ mw.loader.testCallback = undefined;
164163
165164 }, function() {
166165 start();
Index: trunk/phase3/tests/qunit/jquery.qunit.completenessTest.config.js
@@ -0,0 +1,20 @@
 2+// Return true to ignore
 3+var mwTestIgnore = function( val, tester, funcPath ) {
 4+
 5+ // Don't record methods of the properties of mw.Map instances
 6+ // Because we're therefor skipping any injection for
 7+ // "new mw.Map()", manually set it to true here.
 8+ if ( val instanceof mw.Map ) {
 9+ tester.methodCallTracker['Map'] = true;
 10+ return true;
 11+ }
 12+
 13+ // Don't record methods of the properties of a jQuery object
 14+ if ( val instanceof $ ) {
 15+ return true;
 16+ }
 17+
 18+ return false;
 19+};
 20+
 21+var mwTester = new CompletenessTest( mw, mwTestIgnore );
Property changes on: trunk/phase3/tests/qunit/jquery.qunit.completenessTest.config.js
___________________________________________________________________
Added: svn:eol-style
122 + native
Index: trunk/phase3/resources/jquery/jquery.qunit.completenessTest.js
@@ -0,0 +1,223 @@
 2+/**
 3+ * jQuery QUnit CompletenessTest 0.3
 4+ *
 5+ * Tests the completeness of test suites for object oriented javascript
 6+ * libraries. Written to be used in enviroments with jQuery and QUnit.
 7+ * Requires jQuery 1.5.2 or higher.
 8+ *
 9+ * Globals: jQuery, $, QUnit, console.log
 10+ *
 11+ * Built for and tested with:
 12+ * - Safari 5
 13+ * - Firefox 4
 14+ *
 15+ * @author Timo Tijhof, 2011
 16+ */
 17+(function(){
 18+
 19+/* Private members */
 20+var TYPE_SIMPLEFUNC = 101;
 21+var TYPE_OBJCONSTRFUNC = 100;
 22+
 23+/**
 24+ * CompletenessTest
 25+ * @constructor
 26+ *
 27+ * @example
 28+ * var myTester = new CompletenessTest( myLib );
 29+ * @param masterVariable {Object} The root variable that contains all object
 30+ * members. CompletenessTest will recursively traverse objects and keep track
 31+ * of all methods.
 32+ * @param ignoreFn {Function} Optionally pass a function to filter out certain
 33+ * methods. Example: You may want to filter out instances of jQuery or some
 34+ * other constructor. Otherwise "missingTests" will include all methods that
 35+ * were not called from that instance.
 36+ */
 37+var CompletenessTest = function ( masterVariable, ignoreFn ) {
 38+
 39+ // Keep track in these objects. Keyed by strings with the
 40+ // method names (ie. 'my.foo', 'my.bar', etc.) values are boolean true.
 41+ this.methodCallTracker = {};
 42+ this.missingTests = {};
 43+
 44+ this.ignoreFn = undefined === ignoreFn ? function(){ return false; } : ignoreFn;
 45+
 46+ // Lazy limit in case something weird happends (like recurse (part of) ourself).
 47+ this.lazyLimit = 1000;
 48+ this.lazyCounter = 0;
 49+
 50+ // Bind begin and end to QUnit.
 51+ var that = this;
 52+ QUnit.begin = function(){
 53+ that.checkTests( null, masterVariable, masterVariable, [], CompletenessTest.ACTION_INJECT );
 54+ };
 55+ QUnit.done = function(){
 56+ that.checkTests( null, masterVariable, masterVariable, [], CompletenessTest.ACTION_CHECK );
 57+ console.log( 'CompletenessTest.ACTION_CHECK', that );
 58+
 59+ // Insert HTML into header
 60+
 61+ var makeList = function( blob, title, style ) {
 62+ title = title || 'Values';
 63+ var html = '<div style="'+style+'">'
 64+ + '<strong>' + mw.html.escape(title) + '</strong>';
 65+ $.each( blob, function( key ) {
 66+ html += '<br />' + mw.html.escape(key);
 67+ });
 68+ return html + '<br /><br /><em>&mdash; CompletenessTest</em></div>';
 69+ };
 70+ if ( $.isEmptyObject( that.missingTests ) ) {
 71+ var testResults = makeList( { 'No missing tests!': true }, 'missingTests', 'background: #D2E0E6; color: #366097; padding:1em' );
 72+ } else {
 73+ var testResults = makeList( that.missingTests, 'missingTests', 'background: #EE5757; color: black; padding: 1em' );
 74+ }
 75+ $( '#qunit-testrunner-toolbar' ).prepend( testResults );
 76+ };
 77+
 78+ return this;
 79+};
 80+
 81+/* Static members */
 82+CompletenessTest.ACTION_INJECT = 500;
 83+CompletenessTest.ACTION_CHECK = 501;
 84+
 85+/* Public methods */
 86+CompletenessTest.fn = CompletenessTest.prototype = {
 87+
 88+ /**
 89+ * CompletenessTest.fn.checkTests
 90+ *
 91+ * @param currName {String}
 92+ * @param currVar {mixed}
 93+ * @param masterVariable {Object}
 94+ * @param parentPathArray {Array}
 95+ * @param action {Number} What action is checkTests commanded to do ?
 96+ */
 97+ checkTests: function( currName, currVar, masterVariable, parentPathArray, action ) {
 98+
 99+ // Handle the lazy limit
 100+ this.lazyCounter++;
 101+ if ( this.lazyCounter > this.lazyLimit ) {
 102+ console.log( 'CompletenessTest.fn.checkTests> Limit reached: ' + this.lazyCounter );
 103+ return null;
 104+ }
 105+
 106+ var type = $.type( currVar ),
 107+ that = this;
 108+
 109+ // Hard ignores
 110+ if ( this.ignoreFn( currVar, that, parentPathArray ) ) {
 111+
 112+
 113+ // Functions
 114+ } else if ( type === 'function' ) {
 115+
 116+ /* CHECK MODE */
 117+
 118+ if ( action === CompletenessTest.ACTION_CHECK ) {
 119+
 120+ if ( !currVar.prototype || $.isEmptyObject( currVar.prototype ) ) {
 121+
 122+ that.hasTest( parentPathArray.join( '.' ) );
 123+
 124+ // We don't support checking object constructors yet...
 125+ } else {
 126+
 127+ // ...the prototypes are fine tho
 128+ $.each( currVar.prototype, function( key, value ) {
 129+
 130+ // Clone and brake reference to parentPathArray
 131+ var tmpPathArray = $.extend([], parentPathArray);
 132+ tmpPathArray.push('prototype'); tmpPathArray.push(key);
 133+
 134+ that.hasTest( tmpPathArray.join( '.' ) );
 135+ } );
 136+ }
 137+
 138+ /* INJET MODE */
 139+
 140+ } else if ( action === CompletenessTest.ACTION_INJECT ) {
 141+
 142+ if ( !currVar.prototype || $.isEmptyObject( currVar.prototype ) ) {
 143+
 144+ // Inject check
 145+ that.injectCheck( masterVariable, parentPathArray, function(){
 146+
 147+ that.methodCallTracker[ parentPathArray.join( '.' ) ] = true;
 148+
 149+ }, TYPE_SIMPLEFUNC );
 150+
 151+ // We don't support checking object constructors yet...
 152+ } else {
 153+
 154+ // ... the prototypes are fine tho
 155+ $.each( currVar.prototype, function( key, value ) {
 156+
 157+ // Clone and brake reference to parentPathArray
 158+ var tmpPathArray = $.extend([], parentPathArray);
 159+ tmpPathArray.push('prototype'); tmpPathArray.push(key);
 160+
 161+ that.checkTests( key, value, masterVariable, tmpPathArray, action );
 162+ } );
 163+ }
 164+
 165+ } //else { }
 166+
 167+ // Recursively. After all, this *is* the completness test
 168+ } else if ( type === 'object' ) {
 169+
 170+ $.each( currVar, function( key, value ) {
 171+
 172+ // Clone and brake reference to parentPathArray
 173+ var tmpPathArray = $.extend([], parentPathArray);
 174+ tmpPathArray.push(key);
 175+
 176+ that.checkTests( key, value, masterVariable, tmpPathArray, action );
 177+
 178+ } );
 179+
 180+ } // else { }
 181+
 182+ return 'End of checkTests';
 183+ },
 184+
 185+ /**
 186+ * CompletenessTest.fn.hasTest
 187+ *
 188+ * @param fnName {String}
 189+ */
 190+ hasTest: function( fnName ) {
 191+ if ( !(fnName in this.methodCallTracker) ) {
 192+ this.missingTests[fnName] = true;
 193+ }
 194+ },
 195+
 196+ /**
 197+ * CompletenessTest.fn.injectCheck
 198+ *
 199+ * @param masterVariable {Object}
 200+ * @param objectPathArray {Array}
 201+ * @param injectFn {Function}
 202+ */
 203+ injectCheck: function( masterVariable, objectPathArray, injectFn, functionType ) {
 204+ var prev,
 205+ curr = masterVariable,
 206+ lastMember;
 207+
 208+ $.each(objectPathArray, function(i, memberName){
 209+ prev = curr;
 210+ curr = prev[memberName];
 211+ lastMember = memberName;
 212+ });
 213+
 214+ // Objects are by reference, members (unless objects) are not.
 215+ prev[lastMember] = function(){
 216+ injectFn();
 217+ return curr.apply(this, arguments );
 218+ };
 219+ }
 220+};
 221+
 222+window.CompletenessTest = CompletenessTest;
 223+
 224+})();
Property changes on: trunk/phase3/resources/jquery/jquery.qunit.completenessTest.js
___________________________________________________________________
Added: svn:eol-style
1225 + native
Index: trunk/phase3/resources/jquery/jquery.js
@@ -1,28 +1,30 @@
22 /*!
3 - * jQuery JavaScript Library v1.4.4
 3+ * jQuery JavaScript Library v1.6.1
44 * http://jquery.com/
55 *
6 - * Copyright 2010, John Resig
 6+ * Copyright 2011, John Resig
77 * Dual licensed under the MIT or GPL Version 2 licenses.
88 * http://jquery.org/license
99 *
1010 * Includes Sizzle.js
1111 * http://sizzlejs.com/
12 - * Copyright 2010, The Dojo Foundation
 12+ * Copyright 2011, The Dojo Foundation
1313 * Released under the MIT, BSD, and GPL Licenses.
1414 *
15 - * Date: Thu Nov 11 19:04:53 2010 -0500
 15+ * Date: Thu May 12 15:04:36 2011 -0400
1616 */
1717 (function( window, undefined ) {
1818
1919 // Use the correct document accordingly with window argument (sandbox)
20 -var document = window.document;
 20+var document = window.document,
 21+ navigator = window.navigator,
 22+ location = window.location;
2123 var jQuery = (function() {
2224
2325 // Define a local copy of jQuery
2426 var jQuery = function( selector, context ) {
2527 // The jQuery object is actually just the init constructor 'enhanced'
26 - return new jQuery.fn.init( selector, context );
 28+ return new jQuery.fn.init( selector, context, rootjQuery );
2729 },
2830
2931 // Map over jQuery in case of overwrite
@@ -36,22 +38,15 @@
3739
3840 // A simple way to check for HTML strings or ID strings
3941 // (both of which we optimize for)
40 - quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
 42+ quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
4143
42 - // Is it a simple selector
43 - isSimple = /^.[^:#\[\.,]*$/,
44 -
4544 // Check if a string has a non-whitespace character in it
4645 rnotwhite = /\S/,
47 - rwhite = /\s/,
4846
4947 // Used for trimming whitespace
5048 trimLeft = /^\s+/,
5149 trimRight = /\s+$/,
5250
53 - // Check for non-word characters
54 - rnonword = /\W/,
55 -
5651 // Check for digits
5752 rdigit = /\d/,
5853
@@ -75,13 +70,10 @@
7671
7772 // For matching the engine and version of the browser
7873 browserMatch,
79 -
80 - // Has the ready events already been bound?
81 - readyBound = false,
82 -
83 - // The functions to execute on DOM ready
84 - readyList = [],
8574
 75+ // The deferred used on DOM ready
 76+ readyList,
 77+
8678 // The ready event handler
8779 DOMContentLoaded,
8880
@@ -92,12 +84,13 @@
9385 slice = Array.prototype.slice,
9486 trim = String.prototype.trim,
9587 indexOf = Array.prototype.indexOf,
96 -
 88+
9789 // [[Class]] -> type pairs
9890 class2type = {};
9991
10092 jQuery.fn = jQuery.prototype = {
101 - init: function( selector, context ) {
 93+ constructor: jQuery,
 94+ init: function( selector, context, rootjQuery ) {
10295 var match, elem, ret, doc;
10396
10497 // Handle $(""), $(null), or $(undefined)
@@ -111,12 +104,12 @@
112105 this.length = 1;
113106 return this;
114107 }
115 -
 108+
116109 // The body element only exists once, optimize finding it
117110 if ( selector === "body" && !context && document.body ) {
118111 this.context = document;
119112 this[0] = document.body;
120 - this.selector = "body";
 113+ this.selector = selector;
121114 this.length = 1;
122115 return this;
123116 }
@@ -124,13 +117,20 @@
125118 // Handle HTML strings
126119 if ( typeof selector === "string" ) {
127120 // Are we dealing with HTML string or an ID?
128 - match = quickExpr.exec( selector );
 121+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
 122+ // Assume that strings that start and end with <> are HTML and skip the regex check
 123+ match = [ null, selector, null ];
129124
 125+ } else {
 126+ match = quickExpr.exec( selector );
 127+ }
 128+
130129 // Verify a match, and that no context was specified for #id
131130 if ( match && (match[1] || !context) ) {
132131
133132 // HANDLE: $(html) -> $(array)
134133 if ( match[1] ) {
 134+ context = context instanceof jQuery ? context[0] : context;
135135 doc = (context ? context.ownerDocument || context : document);
136136
137137 // If a single string is passed in and it's a single tag
@@ -148,11 +148,11 @@
149149
150150 } else {
151151 ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
152 - selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
 152+ selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;
153153 }
154 -
 154+
155155 return jQuery.merge( this, selector );
156 -
 156+
157157 // HANDLE: $("#id")
158158 } else {
159159 elem = document.getElementById( match[2] );
@@ -176,13 +176,6 @@
177177 return this;
178178 }
179179
180 - // HANDLE: $("TAG")
181 - } else if ( !context && !rnonword.test( selector ) ) {
182 - this.selector = selector;
183 - this.context = document;
184 - selector = document.getElementsByTagName( selector );
185 - return jQuery.merge( this, selector );
186 -
187180 // HANDLE: $(expr, $(...))
188181 } else if ( !context || context.jquery ) {
189182 return (context || rootjQuery).find( selector );
@@ -190,7 +183,7 @@
191184 // HANDLE: $(expr, context)
192185 // (which is just equivalent to: $(context).find(expr)
193186 } else {
194 - return jQuery( context ).find( selector );
 187+ return this.constructor( context ).find( selector );
195188 }
196189
197190 // HANDLE: $(function)
@@ -211,7 +204,7 @@
212205 selector: "",
213206
214207 // The current version of jQuery being used
215 - jquery: "1.4.4",
 208+ jquery: "1.6.1",
216209
217210 // The default length of a jQuery object is 0
218211 length: 0,
@@ -234,18 +227,18 @@
235228 this.toArray() :
236229
237230 // Return just the object
238 - ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
 231+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
239232 },
240233
241234 // Take an array of elements and push it onto the stack
242235 // (returning the new matched element set)
243236 pushStack: function( elems, name, selector ) {
244237 // Build a new jQuery matched element set
245 - var ret = jQuery();
 238+ var ret = this.constructor();
246239
247240 if ( jQuery.isArray( elems ) ) {
248241 push.apply( ret, elems );
249 -
 242+
250243 } else {
251244 jQuery.merge( ret, elems );
252245 }
@@ -271,25 +264,17 @@
272265 each: function( callback, args ) {
273266 return jQuery.each( this, callback, args );
274267 },
275 -
 268+
276269 ready: function( fn ) {
277270 // Attach the listeners
278271 jQuery.bindReady();
279272
280 - // If the DOM is already ready
281 - if ( jQuery.isReady ) {
282 - // Execute the function immediately
283 - fn.call( document, jQuery );
 273+ // Add the callback
 274+ readyList.done( fn );
284275
285 - // Otherwise, remember the function for later
286 - } else if ( readyList ) {
287 - // Add the function to the wait list
288 - readyList.push( fn );
289 - }
290 -
291276 return this;
292277 },
293 -
 278+
294279 eq: function( i ) {
295280 return i === -1 ?
296281 this.slice( i ) :
@@ -314,9 +299,9 @@
315300 return callback.call( elem, i, elem );
316301 }));
317302 },
318 -
 303+
319304 end: function() {
320 - return this.prevObject || jQuery(null);
 305+ return this.prevObject || this.constructor(null);
321306 },
322307
323308 // For internal use only.
@@ -330,7 +315,7 @@
331316 jQuery.fn.init.prototype = jQuery.fn;
332317
333318 jQuery.extend = jQuery.fn.extend = function() {
334 - var options, name, src, copy, copyIsArray, clone,
 319+ var options, name, src, copy, copyIsArray, clone,
335320 target = arguments[0] || {},
336321 i = 1,
337322 length = arguments.length,
@@ -395,31 +380,37 @@
396381
397382 jQuery.extend({
398383 noConflict: function( deep ) {
399 - window.$ = _$;
 384+ if ( window.$ === jQuery ) {
 385+ window.$ = _$;
 386+ }
400387
401 - if ( deep ) {
 388+ if ( deep && window.jQuery === jQuery ) {
402389 window.jQuery = _jQuery;
403390 }
404391
405392 return jQuery;
406393 },
407 -
 394+
408395 // Is the DOM ready to be used? Set to true once it occurs.
409396 isReady: false,
410397
411398 // A counter to track how many items to wait for before
412399 // the ready event fires. See #6781
413400 readyWait: 1,
414 -
 401+
 402+ // Hold (or release) the ready event
 403+ holdReady: function( hold ) {
 404+ if ( hold ) {
 405+ jQuery.readyWait++;
 406+ } else {
 407+ jQuery.ready( true );
 408+ }
 409+ },
 410+
415411 // Handle when the DOM is ready
416412 ready: function( wait ) {
417 - // A third-party is pushing the ready event forwards
418 - if ( wait === true ) {
419 - jQuery.readyWait--;
420 - }
421 -
422 - // Make sure that the DOM is not already loaded
423 - if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) {
 413+ // Either a released hold or an DOMready/load event and not yet ready
 414+ if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
424415 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
425416 if ( !document.body ) {
426417 return setTimeout( jQuery.ready, 1 );
@@ -434,33 +425,21 @@
435426 }
436427
437428 // If there are functions bound, to execute
438 - if ( readyList ) {
439 - // Execute all of them
440 - var fn,
441 - i = 0,
442 - ready = readyList;
 429+ readyList.resolveWith( document, [ jQuery ] );
443430
444 - // Reset the list of functions
445 - readyList = null;
446 -
447 - while ( (fn = ready[ i++ ]) ) {
448 - fn.call( document, jQuery );
449 - }
450 -
451 - // Trigger any bound ready events
452 - if ( jQuery.fn.trigger ) {
453 - jQuery( document ).trigger( "ready" ).unbind( "ready" );
454 - }
 431+ // Trigger any bound ready events
 432+ if ( jQuery.fn.trigger ) {
 433+ jQuery( document ).trigger( "ready" ).unbind( "ready" );
455434 }
456435 }
457436 },
458 -
 437+
459438 bindReady: function() {
460 - if ( readyBound ) {
 439+ if ( readyList ) {
461440 return;
462441 }
463442
464 - readyBound = true;
 443+ readyList = jQuery._Deferred();
465444
466445 // Catch cases where $(document).ready() is called after the
467446 // browser event has already occurred.
@@ -473,7 +452,7 @@
474453 if ( document.addEventListener ) {
475454 // Use the handy event callback
476455 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
477 -
 456+
478457 // A fallback to window.onload, that will always work
479458 window.addEventListener( "load", jQuery.ready, false );
480459
@@ -481,8 +460,8 @@
482461 } else if ( document.attachEvent ) {
483462 // ensure firing before onload,
484463 // maybe late but safe also for iframes
485 - document.attachEvent("onreadystatechange", DOMContentLoaded);
486 -
 464+ document.attachEvent( "onreadystatechange", DOMContentLoaded );
 465+
487466 // A fallback to window.onload, that will always work
488467 window.attachEvent( "onload", jQuery.ready );
489468
@@ -533,20 +512,20 @@
534513 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
535514 return false;
536515 }
537 -
 516+
538517 // Not own constructor property must be Object
539518 if ( obj.constructor &&
540519 !hasOwn.call(obj, "constructor") &&
541520 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
542521 return false;
543522 }
544 -
 523+
545524 // Own properties are enumerated firstly, so to speed up,
546525 // if last one is own, then all properties are own.
547 -
 526+
548527 var key;
549528 for ( key in obj ) {}
550 -
 529+
551530 return key === undefined || hasOwn.call( obj, key );
552531 },
553532
@@ -556,11 +535,11 @@
557536 }
558537 return true;
559538 },
560 -
 539+
561540 error: function( msg ) {
562541 throw msg;
563542 },
564 -
 543+
565544 parseJSON: function( data ) {
566545 if ( typeof data !== "string" || !data ) {
567546 return null;
@@ -568,45 +547,59 @@
569548
570549 // Make sure leading/trailing whitespace is removed (IE can't handle it)
571550 data = jQuery.trim( data );
572 -
 551+
 552+ // Attempt to parse using the native JSON parser first
 553+ if ( window.JSON && window.JSON.parse ) {
 554+ return window.JSON.parse( data );
 555+ }
 556+
573557 // Make sure the incoming data is actual JSON
574558 // Logic borrowed from http://json.org/json2.js
575 - if ( rvalidchars.test(data.replace(rvalidescape, "@")
576 - .replace(rvalidtokens, "]")
577 - .replace(rvalidbraces, "")) ) {
 559+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
 560+ .replace( rvalidtokens, "]" )
 561+ .replace( rvalidbraces, "")) ) {
578562
579 - // Try to use the native JSON parser first
580 - return window.JSON && window.JSON.parse ?
581 - window.JSON.parse( data ) :
582 - (new Function("return " + data))();
 563+ return (new Function( "return " + data ))();
583564
584 - } else {
585 - jQuery.error( "Invalid JSON: " + data );
586565 }
 566+ jQuery.error( "Invalid JSON: " + data );
587567 },
588568
589 - noop: function() {},
 569+ // Cross-browser xml parsing
 570+ // (xml & tmp used internally)
 571+ parseXML: function( data , xml , tmp ) {
590572
591 - // Evalulates a script in a global context
592 - globalEval: function( data ) {
593 - if ( data && rnotwhite.test(data) ) {
594 - // Inspired by code by Andrea Giammarchi
595 - // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
596 - var head = document.getElementsByTagName("head")[0] || document.documentElement,
597 - script = document.createElement("script");
 573+ if ( window.DOMParser ) { // Standard
 574+ tmp = new DOMParser();
 575+ xml = tmp.parseFromString( data , "text/xml" );
 576+ } else { // IE
 577+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
 578+ xml.async = "false";
 579+ xml.loadXML( data );
 580+ }
598581
599 - script.type = "text/javascript";
 582+ tmp = xml.documentElement;
600583
601 - if ( jQuery.support.scriptEval ) {
602 - script.appendChild( document.createTextNode( data ) );
603 - } else {
604 - script.text = data;
605 - }
 584+ if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
 585+ jQuery.error( "Invalid XML: " + data );
 586+ }
606587
607 - // Use insertBefore instead of appendChild to circumvent an IE6 bug.
608 - // This arises when a base node is used (#2709).
609 - head.insertBefore( script, head.firstChild );
610 - head.removeChild( script );
 588+ return xml;
 589+ },
 590+
 591+ noop: function() {},
 592+
 593+ // Evaluates a script in a global context
 594+ // Workarounds based on findings by Jim Driscoll
 595+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
 596+ globalEval: function( data ) {
 597+ if ( data && rnotwhite.test( data ) ) {
 598+ // We use execScript on Internet Explorer
 599+ // We use an anonymous function so that context is window
 600+ // rather than jQuery in Firefox
 601+ ( window.execScript || function( data ) {
 602+ window[ "eval" ].call( window, data );
 603+ } )( data );
611604 }
612605 },
613606
@@ -618,7 +611,7 @@
619612 each: function( object, callback, args ) {
620613 var name, i = 0,
621614 length = object.length,
622 - isObj = length === undefined || jQuery.isFunction(object);
 615+ isObj = length === undefined || jQuery.isFunction( object );
623616
624617 if ( args ) {
625618 if ( isObj ) {
@@ -644,8 +637,11 @@
645638 }
646639 }
647640 } else {
648 - for ( var value = object[0];
649 - i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
 641+ for ( ; i < length; ) {
 642+ if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
 643+ break;
 644+ }
 645+ }
650646 }
651647 }
652648
@@ -676,7 +672,7 @@
677673 // The extra typeof function check is to prevent crashes
678674 // in Safari 2 (See: #3039)
679675 // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
680 - var type = jQuery.type(array);
 676+ var type = jQuery.type( array );
681677
682678 if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
683679 push.call( ret, array );
@@ -689,8 +685,9 @@
690686 },
691687
692688 inArray: function( elem, array ) {
693 - if ( array.indexOf ) {
694 - return array.indexOf( elem );
 689+
 690+ if ( indexOf ) {
 691+ return indexOf.call( array, elem );
695692 }
696693
697694 for ( var i = 0, length = array.length; i < length; i++ ) {
@@ -710,7 +707,7 @@
711708 for ( var l = second.length; j < l; j++ ) {
712709 first[ i++ ] = second[ j ];
713710 }
714 -
 711+
715712 } else {
716713 while ( second[j] !== undefined ) {
717714 first[ i++ ] = second[ j++ ];
@@ -740,49 +737,64 @@
741738
742739 // arg is for internal usage only
743740 map: function( elems, callback, arg ) {
744 - var ret = [], value;
 741+ var value, key, ret = [],
 742+ i = 0,
 743+ length = elems.length,
 744+ // jquery objects are treated as arrays
 745+ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
745746
746747 // Go through the array, translating each of the items to their
747 - // new value (or values).
748 - for ( var i = 0, length = elems.length; i < length; i++ ) {
749 - value = callback( elems[ i ], i, arg );
 748+ if ( isArray ) {
 749+ for ( ; i < length; i++ ) {
 750+ value = callback( elems[ i ], i, arg );
750751
751 - if ( value != null ) {
752 - ret[ ret.length ] = value;
 752+ if ( value != null ) {
 753+ ret[ ret.length ] = value;
 754+ }
753755 }
 756+
 757+ // Go through every key on the object,
 758+ } else {
 759+ for ( key in elems ) {
 760+ value = callback( elems[ key ], key, arg );
 761+
 762+ if ( value != null ) {
 763+ ret[ ret.length ] = value;
 764+ }
 765+ }
754766 }
755767
 768+ // Flatten any nested arrays
756769 return ret.concat.apply( [], ret );
757770 },
758771
759772 // A global GUID counter for objects
760773 guid: 1,
761774
762 - proxy: function( fn, proxy, thisObject ) {
763 - if ( arguments.length === 2 ) {
764 - if ( typeof proxy === "string" ) {
765 - thisObject = fn;
766 - fn = thisObject[ proxy ];
767 - proxy = undefined;
 775+ // Bind a function to a context, optionally partially applying any
 776+ // arguments.
 777+ proxy: function( fn, context ) {
 778+ if ( typeof context === "string" ) {
 779+ var tmp = fn[ context ];
 780+ context = fn;
 781+ fn = tmp;
 782+ }
768783
769 - } else if ( proxy && !jQuery.isFunction( proxy ) ) {
770 - thisObject = proxy;
771 - proxy = undefined;
772 - }
 784+ // Quick check to determine if target is callable, in the spec
 785+ // this throws a TypeError, but we will just return undefined.
 786+ if ( !jQuery.isFunction( fn ) ) {
 787+ return undefined;
773788 }
774789
775 - if ( !proxy && fn ) {
 790+ // Simulated bind
 791+ var args = slice.call( arguments, 2 ),
776792 proxy = function() {
777 - return fn.apply( thisObject || this, arguments );
 793+ return fn.apply( context, args.concat( slice.call( arguments ) ) );
778794 };
779 - }
780795
781796 // Set the guid of unique handler to the same of original handler, so it can be removed
782 - if ( fn ) {
783 - proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
784 - }
 797+ proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
785798
786 - // So proxy can be declared as an argument
787799 return proxy;
788800 },
789801
@@ -790,7 +802,7 @@
791803 // The value/s can be optionally by executed if its a function
792804 access: function( elems, key, value, exec, fn, pass ) {
793805 var length = elems.length;
794 -
 806+
795807 // Setting many attributes
796808 if ( typeof key === "object" ) {
797809 for ( var k in key ) {
@@ -798,19 +810,19 @@
799811 }
800812 return elems;
801813 }
802 -
 814+
803815 // Setting one attribute
804816 if ( value !== undefined ) {
805817 // Optionally, function values get executed if exec is true
806818 exec = !pass && exec && jQuery.isFunction(value);
807 -
 819+
808820 for ( var i = 0; i < length; i++ ) {
809821 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
810822 }
811 -
 823+
812824 return elems;
813825 }
814 -
 826+
815827 // Getting an attribute
816828 return length ? fn( elems[0], key ) : undefined;
817829 },
@@ -833,6 +845,27 @@
834846 return { browser: match[1] || "", version: match[2] || "0" };
835847 },
836848
 849+ sub: function() {
 850+ function jQuerySub( selector, context ) {
 851+ return new jQuerySub.fn.init( selector, context );
 852+ }
 853+ jQuery.extend( true, jQuerySub, this );
 854+ jQuerySub.superclass = this;
 855+ jQuerySub.fn = jQuerySub.prototype = this();
 856+ jQuerySub.fn.constructor = jQuerySub;
 857+ jQuerySub.sub = this.sub;
 858+ jQuerySub.fn.init = function init( selector, context ) {
 859+ if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
 860+ context = jQuerySub( context );
 861+ }
 862+
 863+ return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
 864+ };
 865+ jQuerySub.fn.init.prototype = jQuerySub.fn;
 866+ var rootjQuerySub = jQuerySub(document);
 867+ return jQuerySub;
 868+ },
 869+
837870 browser: {}
838871 });
839872
@@ -852,15 +885,8 @@
853886 jQuery.browser.safari = true;
854887 }
855888
856 -if ( indexOf ) {
857 - jQuery.inArray = function( elem, array ) {
858 - return indexOf.call( array, elem );
859 - };
860 -}
861 -
862 -// Verify that \s matches non-breaking spaces
863 -// (IE fails on this test)
864 -if ( !rwhite.test( "\xA0" ) ) {
 889+// IE doesn't match non-breaking spaces with \s
 890+if ( rnotwhite.test( "\xA0" ) ) {
865891 trimLeft = /^[\s\xA0]+/;
866892 trimRight = /[\s\xA0]+$/;
867893 }
@@ -905,52 +931,265 @@
906932 }
907933
908934 // Expose jQuery to the global object
909 -return (window.jQuery = window.$ = jQuery);
 935+return jQuery;
910936
911937 })();
912938
913939
914 -(function() {
 940+var // Promise methods
 941+ promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ),
 942+ // Static reference to slice
 943+ sliceDeferred = [].slice;
915944
916 - jQuery.support = {};
 945+jQuery.extend({
 946+ // Create a simple deferred (one callbacks list)
 947+ _Deferred: function() {
 948+ var // callbacks list
 949+ callbacks = [],
 950+ // stored [ context , args ]
 951+ fired,
 952+ // to avoid firing when already doing so
 953+ firing,
 954+ // flag to know if the deferred has been cancelled
 955+ cancelled,
 956+ // the deferred itself
 957+ deferred = {
917958
918 - var root = document.documentElement,
919 - script = document.createElement("script"),
920 - div = document.createElement("div"),
921 - id = "script" + jQuery.now();
 959+ // done( f1, f2, ...)
 960+ done: function() {
 961+ if ( !cancelled ) {
 962+ var args = arguments,
 963+ i,
 964+ length,
 965+ elem,
 966+ type,
 967+ _fired;
 968+ if ( fired ) {
 969+ _fired = fired;
 970+ fired = 0;
 971+ }
 972+ for ( i = 0, length = args.length; i < length; i++ ) {
 973+ elem = args[ i ];
 974+ type = jQuery.type( elem );
 975+ if ( type === "array" ) {
 976+ deferred.done.apply( deferred, elem );
 977+ } else if ( type === "function" ) {
 978+ callbacks.push( elem );
 979+ }
 980+ }
 981+ if ( _fired ) {
 982+ deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
 983+ }
 984+ }
 985+ return this;
 986+ },
922987
923 - div.style.display = "none";
924 - div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
 988+ // resolve with given context and args
 989+ resolveWith: function( context, args ) {
 990+ if ( !cancelled && !fired && !firing ) {
 991+ // make sure args are available (#8421)
 992+ args = args || [];
 993+ firing = 1;
 994+ try {
 995+ while( callbacks[ 0 ] ) {
 996+ callbacks.shift().apply( context, args );
 997+ }
 998+ }
 999+ finally {
 1000+ fired = [ context, args ];
 1001+ firing = 0;
 1002+ }
 1003+ }
 1004+ return this;
 1005+ },
9251006
926 - var all = div.getElementsByTagName("*"),
927 - a = div.getElementsByTagName("a")[0],
928 - select = document.createElement("select"),
929 - opt = select.appendChild( document.createElement("option") );
 1007+ // resolve with this as context and given arguments
 1008+ resolve: function() {
 1009+ deferred.resolveWith( this, arguments );
 1010+ return this;
 1011+ },
9301012
 1013+ // Has this deferred been resolved?
 1014+ isResolved: function() {
 1015+ return !!( firing || fired );
 1016+ },
 1017+
 1018+ // Cancel
 1019+ cancel: function() {
 1020+ cancelled = 1;
 1021+ callbacks = [];
 1022+ return this;
 1023+ }
 1024+ };
 1025+
 1026+ return deferred;
 1027+ },
 1028+
 1029+ // Full fledged deferred (two callbacks list)
 1030+ Deferred: function( func ) {
 1031+ var deferred = jQuery._Deferred(),
 1032+ failDeferred = jQuery._Deferred(),
 1033+ promise;
 1034+ // Add errorDeferred methods, then and promise
 1035+ jQuery.extend( deferred, {
 1036+ then: function( doneCallbacks, failCallbacks ) {
 1037+ deferred.done( doneCallbacks ).fail( failCallbacks );
 1038+ return this;
 1039+ },
 1040+ always: function() {
 1041+ return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );
 1042+ },
 1043+ fail: failDeferred.done,
 1044+ rejectWith: failDeferred.resolveWith,
 1045+ reject: failDeferred.resolve,
 1046+ isRejected: failDeferred.isResolved,
 1047+ pipe: function( fnDone, fnFail ) {
 1048+ return jQuery.Deferred(function( newDefer ) {
 1049+ jQuery.each( {
 1050+ done: [ fnDone, "resolve" ],
 1051+ fail: [ fnFail, "reject" ]
 1052+ }, function( handler, data ) {
 1053+ var fn = data[ 0 ],
 1054+ action = data[ 1 ],
 1055+ returned;
 1056+ if ( jQuery.isFunction( fn ) ) {
 1057+ deferred[ handler ](function() {
 1058+ returned = fn.apply( this, arguments );
 1059+ if ( returned && jQuery.isFunction( returned.promise ) ) {
 1060+ returned.promise().then( newDefer.resolve, newDefer.reject );
 1061+ } else {
 1062+ newDefer[ action ]( returned );
 1063+ }
 1064+ });
 1065+ } else {
 1066+ deferred[ handler ]( newDefer[ action ] );
 1067+ }
 1068+ });
 1069+ }).promise();
 1070+ },
 1071+ // Get a promise for this deferred
 1072+ // If obj is provided, the promise aspect is added to the object
 1073+ promise: function( obj ) {
 1074+ if ( obj == null ) {
 1075+ if ( promise ) {
 1076+ return promise;
 1077+ }
 1078+ promise = obj = {};
 1079+ }
 1080+ var i = promiseMethods.length;
 1081+ while( i-- ) {
 1082+ obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
 1083+ }
 1084+ return obj;
 1085+ }
 1086+ });
 1087+ // Make sure only one callback list will be used
 1088+ deferred.done( failDeferred.cancel ).fail( deferred.cancel );
 1089+ // Unexpose cancel
 1090+ delete deferred.cancel;
 1091+ // Call given func if any
 1092+ if ( func ) {
 1093+ func.call( deferred, deferred );
 1094+ }
 1095+ return deferred;
 1096+ },
 1097+
 1098+ // Deferred helper
 1099+ when: function( firstParam ) {
 1100+ var args = arguments,
 1101+ i = 0,
 1102+ length = args.length,
 1103+ count = length,
 1104+ deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
 1105+ firstParam :
 1106+ jQuery.Deferred();
 1107+ function resolveFunc( i ) {
 1108+ return function( value ) {
 1109+ args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
 1110+ if ( !( --count ) ) {
 1111+ // Strange bug in FF4:
 1112+ // Values changed onto the arguments object sometimes end up as undefined values
 1113+ // outside the $.when method. Cloning the object into a fresh array solves the issue
 1114+ deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );
 1115+ }
 1116+ };
 1117+ }
 1118+ if ( length > 1 ) {
 1119+ for( ; i < length; i++ ) {
 1120+ if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {
 1121+ args[ i ].promise().then( resolveFunc(i), deferred.reject );
 1122+ } else {
 1123+ --count;
 1124+ }
 1125+ }
 1126+ if ( !count ) {
 1127+ deferred.resolveWith( deferred, args );
 1128+ }
 1129+ } else if ( deferred !== firstParam ) {
 1130+ deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
 1131+ }
 1132+ return deferred.promise();
 1133+ }
 1134+});
 1135+
 1136+
 1137+
 1138+jQuery.support = (function() {
 1139+
 1140+ var div = document.createElement( "div" ),
 1141+ documentElement = document.documentElement,
 1142+ all,
 1143+ a,
 1144+ select,
 1145+ opt,
 1146+ input,
 1147+ marginDiv,
 1148+ support,
 1149+ fragment,
 1150+ body,
 1151+ bodyStyle,
 1152+ tds,
 1153+ events,
 1154+ eventName,
 1155+ i,
 1156+ isSupported;
 1157+
 1158+ // Preliminary tests
 1159+ div.setAttribute("className", "t");
 1160+ div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
 1161+
 1162+ all = div.getElementsByTagName( "*" );
 1163+ a = div.getElementsByTagName( "a" )[ 0 ];
 1164+
9311165 // Can't get basic test support
9321166 if ( !all || !all.length || !a ) {
933 - return;
 1167+ return {};
9341168 }
9351169
936 - jQuery.support = {
 1170+ // First batch of supports tests
 1171+ select = document.createElement( "select" );
 1172+ opt = select.appendChild( document.createElement("option") );
 1173+ input = div.getElementsByTagName( "input" )[ 0 ];
 1174+
 1175+ support = {
9371176 // IE strips leading whitespace when .innerHTML is used
938 - leadingWhitespace: div.firstChild.nodeType === 3,
 1177+ leadingWhitespace: ( div.firstChild.nodeType === 3 ),
9391178
9401179 // Make sure that tbody elements aren't automatically inserted
9411180 // IE will insert them into empty tables
942 - tbody: !div.getElementsByTagName("tbody").length,
 1181+ tbody: !div.getElementsByTagName( "tbody" ).length,
9431182
9441183 // Make sure that link elements get serialized correctly by innerHTML
9451184 // This requires a wrapper element in IE
946 - htmlSerialize: !!div.getElementsByTagName("link").length,
 1185+ htmlSerialize: !!div.getElementsByTagName( "link" ).length,
9471186
9481187 // Get the style information from getAttribute
949 - // (IE uses .cssText insted)
950 - style: /red/.test( a.getAttribute("style") ),
 1188+ // (IE uses .cssText instead)
 1189+ style: /top/.test( a.getAttribute("style") ),
9511190
9521191 // Make sure that URLs aren't manipulated
9531192 // (IE normalizes it by default)
954 - hrefNormalized: a.getAttribute("href") === "/a",
 1193+ hrefNormalized: ( a.getAttribute( "href" ) === "/a" ),
9551194
9561195 // Make sure that element opacity exists
9571196 // (IE uses filter instead)
@@ -964,150 +1203,183 @@
9651204 // Make sure that if no value is specified for a checkbox
9661205 // that it defaults to "on".
9671206 // (WebKit defaults to "" instead)
968 - checkOn: div.getElementsByTagName("input")[0].value === "on",
 1207+ checkOn: ( input.value === "on" ),
9691208
9701209 // Make sure that a selected-by-default option has a working selected property.
9711210 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
9721211 optSelected: opt.selected,
9731212
 1213+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
 1214+ getSetAttribute: div.className !== "t",
 1215+
9741216 // Will be defined later
 1217+ submitBubbles: true,
 1218+ changeBubbles: true,
 1219+ focusinBubbles: false,
9751220 deleteExpando: true,
976 - optDisabled: false,
977 - checkClone: false,
978 - scriptEval: false,
9791221 noCloneEvent: true,
980 - boxModel: null,
9811222 inlineBlockNeedsLayout: false,
9821223 shrinkWrapBlocks: false,
983 - reliableHiddenOffsets: true
 1224+ reliableMarginRight: true
9841225 };
9851226
 1227+ // Make sure checked status is properly cloned
 1228+ input.checked = true;
 1229+ support.noCloneChecked = input.cloneNode( true ).checked;
 1230+
9861231 // Make sure that the options inside disabled selects aren't marked as disabled
987 - // (WebKit marks them as diabled)
 1232+ // (WebKit marks them as disabled)
9881233 select.disabled = true;
989 - jQuery.support.optDisabled = !opt.disabled;
 1234+ support.optDisabled = !opt.disabled;
9901235
991 - script.type = "text/javascript";
992 - try {
993 - script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
994 - } catch(e) {}
995 -
996 - root.insertBefore( script, root.firstChild );
997 -
998 - // Make sure that the execution of code works by injecting a script
999 - // tag with appendChild/createTextNode
1000 - // (IE doesn't support this, fails, and uses .text instead)
1001 - if ( window[ id ] ) {
1002 - jQuery.support.scriptEval = true;
1003 - delete window[ id ];
1004 - }
1005 -
10061236 // Test to see if it's possible to delete an expando from an element
10071237 // Fails in Internet Explorer
10081238 try {
1009 - delete script.test;
1010 -
1011 - } catch(e) {
1012 - jQuery.support.deleteExpando = false;
 1239+ delete div.test;
 1240+ } catch( e ) {
 1241+ support.deleteExpando = false;
10131242 }
10141243
1015 - root.removeChild( script );
1016 -
1017 - if ( div.attachEvent && div.fireEvent ) {
1018 - div.attachEvent("onclick", function click() {
 1244+ if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
 1245+ div.attachEvent( "onclick", function click() {
10191246 // Cloning a node shouldn't copy over any
10201247 // bound event handlers (IE does this)
1021 - jQuery.support.noCloneEvent = false;
1022 - div.detachEvent("onclick", click);
 1248+ support.noCloneEvent = false;
 1249+ div.detachEvent( "onclick", click );
10231250 });
1024 - div.cloneNode(true).fireEvent("onclick");
 1251+ div.cloneNode( true ).fireEvent( "onclick" );
10251252 }
10261253
1027 - div = document.createElement("div");
1028 - div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
 1254+ // Check if a radio maintains it's value
 1255+ // after being appended to the DOM
 1256+ input = document.createElement("input");
 1257+ input.value = "t";
 1258+ input.setAttribute("type", "radio");
 1259+ support.radioValue = input.value === "t";
10291260
1030 - var fragment = document.createDocumentFragment();
 1261+ input.setAttribute("checked", "checked");
 1262+ div.appendChild( input );
 1263+ fragment = document.createDocumentFragment();
10311264 fragment.appendChild( div.firstChild );
10321265
10331266 // WebKit doesn't clone checked state correctly in fragments
1034 - jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
 1267+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
10351268
 1269+ div.innerHTML = "";
 1270+
10361271 // Figure out if the W3C box model works as expected
1037 - // document.body must exist before we can do this
1038 - jQuery(function() {
1039 - var div = document.createElement("div");
1040 - div.style.width = div.style.paddingLeft = "1px";
 1272+ div.style.width = div.style.paddingLeft = "1px";
10411273
1042 - document.body.appendChild( div );
1043 - jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
 1274+ // We use our own, invisible, body
 1275+ body = document.createElement( "body" );
 1276+ bodyStyle = {
 1277+ visibility: "hidden",
 1278+ width: 0,
 1279+ height: 0,
 1280+ border: 0,
 1281+ margin: 0,
 1282+ // Set background to avoid IE crashes when removing (#9028)
 1283+ background: "none"
 1284+ };
 1285+ for ( i in bodyStyle ) {
 1286+ body.style[ i ] = bodyStyle[ i ];
 1287+ }
 1288+ body.appendChild( div );
 1289+ documentElement.insertBefore( body, documentElement.firstChild );
10441290
1045 - if ( "zoom" in div.style ) {
1046 - // Check if natively block-level elements act like inline-block
1047 - // elements when setting their display to 'inline' and giving
1048 - // them layout
1049 - // (IE < 8 does this)
1050 - div.style.display = "inline";
1051 - div.style.zoom = 1;
1052 - jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2;
 1291+ // Check if a disconnected checkbox will retain its checked
 1292+ // value of true after appended to the DOM (IE6/7)
 1293+ support.appendChecked = input.checked;
10531294
1054 - // Check if elements with layout shrink-wrap their children
1055 - // (IE 6 does this)
1056 - div.style.display = "";
1057 - div.innerHTML = "<div style='width:4px;'></div>";
1058 - jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;
1059 - }
 1295+ support.boxModel = div.offsetWidth === 2;
10601296
1061 - div.innerHTML = "<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";
1062 - var tds = div.getElementsByTagName("td");
 1297+ if ( "zoom" in div.style ) {
 1298+ // Check if natively block-level elements act like inline-block
 1299+ // elements when setting their display to 'inline' and giving
 1300+ // them layout
 1301+ // (IE < 8 does this)
 1302+ div.style.display = "inline";
 1303+ div.style.zoom = 1;
 1304+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
10631305
1064 - // Check if table cells still have offsetWidth/Height when they are set
1065 - // to display:none and there are still other visible table cells in a
1066 - // table row; if so, offsetWidth/Height are not reliable for use when
1067 - // determining if an element has been hidden directly using
1068 - // display:none (it is still safe to use offsets if a parent element is
1069 - // hidden; don safety goggles and see bug #4512 for more information).
1070 - // (only IE 8 fails this test)
1071 - jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0;
 1306+ // Check if elements with layout shrink-wrap their children
 1307+ // (IE 6 does this)
 1308+ div.style.display = "";
 1309+ div.innerHTML = "<div style='width:4px;'></div>";
 1310+ support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
 1311+ }
10721312
1073 - tds[0].style.display = "";
1074 - tds[1].style.display = "none";
 1313+ div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
 1314+ tds = div.getElementsByTagName( "td" );
10751315
1076 - // Check if empty table cells still have offsetWidth/Height
1077 - // (IE < 8 fail this test)
1078 - jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0;
1079 - div.innerHTML = "";
 1316+ // Check if table cells still have offsetWidth/Height when they are set
 1317+ // to display:none and there are still other visible table cells in a
 1318+ // table row; if so, offsetWidth/Height are not reliable for use when
 1319+ // determining if an element has been hidden directly using
 1320+ // display:none (it is still safe to use offsets if a parent element is
 1321+ // hidden; don safety goggles and see bug #4512 for more information).
 1322+ // (only IE 8 fails this test)
 1323+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
10801324
1081 - document.body.removeChild( div ).style.display = "none";
1082 - div = tds = null;
1083 - });
 1325+ tds[ 0 ].style.display = "";
 1326+ tds[ 1 ].style.display = "none";
10841327
 1328+ // Check if empty table cells still have offsetWidth/Height
 1329+ // (IE < 8 fail this test)
 1330+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
 1331+ div.innerHTML = "";
 1332+
 1333+ // Check if div with explicit width and no margin-right incorrectly
 1334+ // gets computed margin-right based on width of container. For more
 1335+ // info see bug #3333
 1336+ // Fails in WebKit before Feb 2011 nightlies
 1337+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
 1338+ if ( document.defaultView && document.defaultView.getComputedStyle ) {
 1339+ marginDiv = document.createElement( "div" );
 1340+ marginDiv.style.width = "0";
 1341+ marginDiv.style.marginRight = "0";
 1342+ div.appendChild( marginDiv );
 1343+ support.reliableMarginRight =
 1344+ ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
 1345+ }
 1346+
 1347+ // Remove the body element we added
 1348+ body.innerHTML = "";
 1349+ documentElement.removeChild( body );
 1350+
10851351 // Technique from Juriy Zaytsev
10861352 // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
1087 - var eventSupported = function( eventName ) {
1088 - var el = document.createElement("div");
1089 - eventName = "on" + eventName;
1090 -
1091 - var isSupported = (eventName in el);
1092 - if ( !isSupported ) {
1093 - el.setAttribute(eventName, "return;");
1094 - isSupported = typeof el[eventName] === "function";
 1353+ // We only care about the case where non-standard event systems
 1354+ // are used, namely in IE. Short-circuiting here helps us to
 1355+ // avoid an eval call (in setAttribute) which can cause CSP
 1356+ // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
 1357+ if ( div.attachEvent ) {
 1358+ for( i in {
 1359+ submit: 1,
 1360+ change: 1,
 1361+ focusin: 1
 1362+ } ) {
 1363+ eventName = "on" + i;
 1364+ isSupported = ( eventName in div );
 1365+ if ( !isSupported ) {
 1366+ div.setAttribute( eventName, "return;" );
 1367+ isSupported = ( typeof div[ eventName ] === "function" );
 1368+ }
 1369+ support[ i + "Bubbles" ] = isSupported;
10951370 }
1096 - el = null;
 1371+ }
10971372
1098 - return isSupported;
1099 - };
 1373+ return support;
 1374+})();
11001375
1101 - jQuery.support.submitBubbles = eventSupported("submit");
1102 - jQuery.support.changeBubbles = eventSupported("change");
 1376+// Keep track of boxModel
 1377+jQuery.boxModel = jQuery.support.boxModel;
11031378
1104 - // release memory in IE
1105 - root = script = div = all = a = null;
1106 -})();
11071379
11081380
11091381
1110 -var windowData = {},
1111 - rbrace = /^(?:\{.*\}|\[.*\])$/;
 1382+var rbrace = /^(?:\{.*\}|\[.*\])$/,
 1383+ rmultiDash = /([a-z])([A-Z])/g;
11121384
11131385 jQuery.extend({
11141386 cache: {},
@@ -1115,8 +1387,9 @@
11161388 // Please use with caution
11171389 uuid: 0,
11181390
1119 - // Unique for each copy of jQuery on the page
1120 - expando: "jQuery" + jQuery.now(),
 1391+ // Unique for each copy of jQuery on the page
 1392+ // Non-digits removed to match rinlinejQuery
 1393+ expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
11211394
11221395 // The following elements throw uncatchable exceptions if you
11231396 // attempt to add expando properties to them.
@@ -1127,103 +1400,185 @@
11281401 "applet": true
11291402 },
11301403
1131 - data: function( elem, name, data ) {
 1404+ hasData: function( elem ) {
 1405+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
 1406+
 1407+ return !!elem && !isEmptyDataObject( elem );
 1408+ },
 1409+
 1410+ data: function( elem, name, data, pvt /* Internal Use Only */ ) {
11321411 if ( !jQuery.acceptData( elem ) ) {
11331412 return;
11341413 }
11351414
1136 - elem = elem == window ?
1137 - windowData :
1138 - elem;
 1415+ var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
11391416
1140 - var isNode = elem.nodeType,
1141 - id = isNode ? elem[ jQuery.expando ] : null,
1142 - cache = jQuery.cache, thisCache;
 1417+ // We have to handle DOM nodes and JS objects differently because IE6-7
 1418+ // can't GC object references properly across the DOM-JS boundary
 1419+ isNode = elem.nodeType,
11431420
1144 - if ( isNode && !id && typeof name === "string" && data === undefined ) {
 1421+ // Only DOM nodes need the global jQuery cache; JS object data is
 1422+ // attached directly to the object so GC can occur automatically
 1423+ cache = isNode ? jQuery.cache : elem,
 1424+
 1425+ // Only defining an ID for JS objects if its cache already exists allows
 1426+ // the code to shortcut on the same path as a DOM node with no cache
 1427+ id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;
 1428+
 1429+ // Avoid doing any more work than we need to when trying to get data on an
 1430+ // object that has no data at all
 1431+ if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {
11451432 return;
11461433 }
11471434
1148 - // Get the data from the object directly
1149 - if ( !isNode ) {
1150 - cache = elem;
 1435+ if ( !id ) {
 1436+ // Only DOM nodes need a new unique ID for each element since their data
 1437+ // ends up in the global cache
 1438+ if ( isNode ) {
 1439+ elem[ jQuery.expando ] = id = ++jQuery.uuid;
 1440+ } else {
 1441+ id = jQuery.expando;
 1442+ }
 1443+ }
11511444
1152 - // Compute a unique ID for the element
1153 - } else if ( !id ) {
1154 - elem[ jQuery.expando ] = id = ++jQuery.uuid;
 1445+ if ( !cache[ id ] ) {
 1446+ cache[ id ] = {};
 1447+
 1448+ // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
 1449+ // metadata on plain JS objects when the object is serialized using
 1450+ // JSON.stringify
 1451+ if ( !isNode ) {
 1452+ cache[ id ].toJSON = jQuery.noop;
 1453+ }
11551454 }
11561455
1157 - // Avoid generating a new cache unless none exists and we
1158 - // want to manipulate it.
1159 - if ( typeof name === "object" ) {
1160 - if ( isNode ) {
 1456+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
 1457+ // shallow copied over onto the existing cache
 1458+ if ( typeof name === "object" || typeof name === "function" ) {
 1459+ if ( pvt ) {
 1460+ cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
 1461+ } else {
11611462 cache[ id ] = jQuery.extend(cache[ id ], name);
 1463+ }
 1464+ }
11621465
1163 - } else {
1164 - jQuery.extend( cache, name );
 1466+ thisCache = cache[ id ];
 1467+
 1468+ // Internal jQuery data is stored in a separate object inside the object's data
 1469+ // cache in order to avoid key collisions between internal data and user-defined
 1470+ // data
 1471+ if ( pvt ) {
 1472+ if ( !thisCache[ internalKey ] ) {
 1473+ thisCache[ internalKey ] = {};
11651474 }
11661475
1167 - } else if ( isNode && !cache[ id ] ) {
1168 - cache[ id ] = {};
 1476+ thisCache = thisCache[ internalKey ];
11691477 }
11701478
1171 - thisCache = isNode ? cache[ id ] : cache;
1172 -
1173 - // Prevent overriding the named cache with undefined values
11741479 if ( data !== undefined ) {
1175 - thisCache[ name ] = data;
 1480+ thisCache[ jQuery.camelCase( name ) ] = data;
11761481 }
11771482
1178 - return typeof name === "string" ? thisCache[ name ] : thisCache;
 1483+ // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
 1484+ // not attempt to inspect the internal events object using jQuery.data, as this
 1485+ // internal data object is undocumented and subject to change.
 1486+ if ( name === "events" && !thisCache[name] ) {
 1487+ return thisCache[ internalKey ] && thisCache[ internalKey ].events;
 1488+ }
 1489+
 1490+ return getByName ? thisCache[ jQuery.camelCase( name ) ] : thisCache;
11791491 },
11801492
1181 - removeData: function( elem, name ) {
 1493+ removeData: function( elem, name, pvt /* Internal Use Only */ ) {
11821494 if ( !jQuery.acceptData( elem ) ) {
11831495 return;
11841496 }
11851497
1186 - elem = elem == window ?
1187 - windowData :
1188 - elem;
 1498+ var internalKey = jQuery.expando, isNode = elem.nodeType,
11891499
1190 - var isNode = elem.nodeType,
1191 - id = isNode ? elem[ jQuery.expando ] : elem,
1192 - cache = jQuery.cache,
1193 - thisCache = isNode ? cache[ id ] : id;
 1500+ // See jQuery.data for more information
 1501+ cache = isNode ? jQuery.cache : elem,
11941502
1195 - // If we want to remove a specific section of the element's data
 1503+ // See jQuery.data for more information
 1504+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
 1505+
 1506+ // If there is already no cache entry for this object, there is no
 1507+ // purpose in continuing
 1508+ if ( !cache[ id ] ) {
 1509+ return;
 1510+ }
 1511+
11961512 if ( name ) {
 1513+ var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
 1514+
11971515 if ( thisCache ) {
1198 - // Remove the section of cache data
11991516 delete thisCache[ name ];
12001517
1201 - // If we've removed all the data, remove the element's cache
1202 - if ( isNode && jQuery.isEmptyObject(thisCache) ) {
1203 - jQuery.removeData( elem );
 1518+ // If there is no data left in the cache, we want to continue
 1519+ // and let the cache object itself get destroyed
 1520+ if ( !isEmptyDataObject(thisCache) ) {
 1521+ return;
12041522 }
12051523 }
 1524+ }
12061525
1207 - // Otherwise, we want to remove all of the element's data
 1526+ // See jQuery.data for more information
 1527+ if ( pvt ) {
 1528+ delete cache[ id ][ internalKey ];
 1529+
 1530+ // Don't destroy the parent cache unless the internal data object
 1531+ // had been the only thing left in it
 1532+ if ( !isEmptyDataObject(cache[ id ]) ) {
 1533+ return;
 1534+ }
 1535+ }
 1536+
 1537+ var internalCache = cache[ id ][ internalKey ];
 1538+
 1539+ // Browsers that fail expando deletion also refuse to delete expandos on
 1540+ // the window, but it will allow it on all other JS objects; other browsers
 1541+ // don't care
 1542+ if ( jQuery.support.deleteExpando || cache != window ) {
 1543+ delete cache[ id ];
12081544 } else {
1209 - if ( isNode && jQuery.support.deleteExpando ) {
 1545+ cache[ id ] = null;
 1546+ }
 1547+
 1548+ // We destroyed the entire user cache at once because it's faster than
 1549+ // iterating through each key, but we need to continue to persist internal
 1550+ // data if it existed
 1551+ if ( internalCache ) {
 1552+ cache[ id ] = {};
 1553+ // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
 1554+ // metadata on plain JS objects when the object is serialized using
 1555+ // JSON.stringify
 1556+ if ( !isNode ) {
 1557+ cache[ id ].toJSON = jQuery.noop;
 1558+ }
 1559+
 1560+ cache[ id ][ internalKey ] = internalCache;
 1561+
 1562+ // Otherwise, we need to eliminate the expando on the node to avoid
 1563+ // false lookups in the cache for entries that no longer exist
 1564+ } else if ( isNode ) {
 1565+ // IE does not allow us to delete expando properties from nodes,
 1566+ // nor does it have a removeAttribute function on Document nodes;
 1567+ // we must handle all of these cases
 1568+ if ( jQuery.support.deleteExpando ) {
12101569 delete elem[ jQuery.expando ];
1211 -
12121570 } else if ( elem.removeAttribute ) {
12131571 elem.removeAttribute( jQuery.expando );
1214 -
1215 - // Completely remove the data cache
1216 - } else if ( isNode ) {
1217 - delete cache[ id ];
1218 -
1219 - // Remove all fields from the object
12201572 } else {
1221 - for ( var n in elem ) {
1222 - delete elem[ n ];
1223 - }
 1573+ elem[ jQuery.expando ] = null;
12241574 }
12251575 }
12261576 },
12271577
 1578+ // For internal use only.
 1579+ _data: function( elem, name, data ) {
 1580+ return jQuery.data( elem, name, data, true );
 1581+ },
 1582+
12281583 // A method for determining if a DOM node can handle the data expando
12291584 acceptData: function( elem ) {
12301585 if ( elem.nodeName ) {
@@ -1244,15 +1599,18 @@
12451600
12461601 if ( typeof key === "undefined" ) {
12471602 if ( this.length ) {
1248 - var attr = this[0].attributes, name;
12491603 data = jQuery.data( this[0] );
12501604
1251 - for ( var i = 0, l = attr.length; i < l; i++ ) {
1252 - name = attr[i].name;
 1605+ if ( this[0].nodeType === 1 ) {
 1606+ var attr = this[0].attributes, name;
 1607+ for ( var i = 0, l = attr.length; i < l; i++ ) {
 1608+ name = attr[i].name;
12531609
1254 - if ( name.indexOf( "data-" ) === 0 ) {
1255 - name = name.substr( 5 );
1256 - dataAttr( this[0], name, data[ name ] );
 1610+ if ( name.indexOf( "data-" ) === 0 ) {
 1611+ name = jQuery.camelCase( name.substring(5) );
 1612+
 1613+ dataAttr( this[0], name, data[ name ] );
 1614+ }
12571615 }
12581616 }
12591617 }
@@ -1304,8 +1662,10 @@
13051663 // If nothing was found internally, try to fetch any
13061664 // data from the HTML5 data-* attribute
13071665 if ( data === undefined && elem.nodeType === 1 ) {
1308 - data = elem.getAttribute( "data-" + key );
 1666+ var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase();
13091667
 1668+ data = elem.getAttribute( name );
 1669+
13101670 if ( typeof data === "string" ) {
13111671 try {
13121672 data = data === "true" ? true :
@@ -1327,38 +1687,92 @@
13281688 return data;
13291689 }
13301690
 1691+// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON
 1692+// property to be considered empty objects; this property always exists in
 1693+// order to make sure JSON.stringify does not expose internal metadata
 1694+function isEmptyDataObject( obj ) {
 1695+ for ( var name in obj ) {
 1696+ if ( name !== "toJSON" ) {
 1697+ return false;
 1698+ }
 1699+ }
13311700
 1701+ return true;
 1702+}
13321703
13331704
1334 -jQuery.extend({
1335 - queue: function( elem, type, data ) {
1336 - if ( !elem ) {
1337 - return;
1338 - }
13391705
1340 - type = (type || "fx") + "queue";
1341 - var q = jQuery.data( elem, type );
13421706
1343 - // Speed up dequeue by getting out quickly if this is just a lookup
1344 - if ( !data ) {
1345 - return q || [];
1346 - }
 1707+function handleQueueMarkDefer( elem, type, src ) {
 1708+ var deferDataKey = type + "defer",
 1709+ queueDataKey = type + "queue",
 1710+ markDataKey = type + "mark",
 1711+ defer = jQuery.data( elem, deferDataKey, undefined, true );
 1712+ if ( defer &&
 1713+ ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&
 1714+ ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {
 1715+ // Give room for hard-coded callbacks to fire first
 1716+ // and eventually mark/queue something else on the element
 1717+ setTimeout( function() {
 1718+ if ( !jQuery.data( elem, queueDataKey, undefined, true ) &&
 1719+ !jQuery.data( elem, markDataKey, undefined, true ) ) {
 1720+ jQuery.removeData( elem, deferDataKey, true );
 1721+ defer.resolve();
 1722+ }
 1723+ }, 0 );
 1724+ }
 1725+}
13471726
1348 - if ( !q || jQuery.isArray(data) ) {
1349 - q = jQuery.data( elem, type, jQuery.makeArray(data) );
 1727+jQuery.extend({
13501728
1351 - } else {
1352 - q.push( data );
 1729+ _mark: function( elem, type ) {
 1730+ if ( elem ) {
 1731+ type = (type || "fx") + "mark";
 1732+ jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true );
13531733 }
 1734+ },
13541735
1355 - return q;
 1736+ _unmark: function( force, elem, type ) {
 1737+ if ( force !== true ) {
 1738+ type = elem;
 1739+ elem = force;
 1740+ force = false;
 1741+ }
 1742+ if ( elem ) {
 1743+ type = type || "fx";
 1744+ var key = type + "mark",
 1745+ count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 );
 1746+ if ( count ) {
 1747+ jQuery.data( elem, key, count, true );
 1748+ } else {
 1749+ jQuery.removeData( elem, key, true );
 1750+ handleQueueMarkDefer( elem, type, "mark" );
 1751+ }
 1752+ }
13561753 },
13571754
 1755+ queue: function( elem, type, data ) {
 1756+ if ( elem ) {
 1757+ type = (type || "fx") + "queue";
 1758+ var q = jQuery.data( elem, type, undefined, true );
 1759+ // Speed up dequeue by getting out quickly if this is just a lookup
 1760+ if ( data ) {
 1761+ if ( !q || jQuery.isArray(data) ) {
 1762+ q = jQuery.data( elem, type, jQuery.makeArray(data), true );
 1763+ } else {
 1764+ q.push( data );
 1765+ }
 1766+ }
 1767+ return q || [];
 1768+ }
 1769+ },
 1770+
13581771 dequeue: function( elem, type ) {
13591772 type = type || "fx";
13601773
13611774 var queue = jQuery.queue( elem, type ),
1362 - fn = queue.shift();
 1775+ fn = queue.shift(),
 1776+ defer;
13631777
13641778 // If the fx queue is dequeued, always remove the progress sentinel
13651779 if ( fn === "inprogress" ) {
@@ -1376,6 +1790,11 @@
13771791 jQuery.dequeue(elem, type);
13781792 });
13791793 }
 1794+
 1795+ if ( !queue.length ) {
 1796+ jQuery.removeData( elem, type + "queue", true );
 1797+ handleQueueMarkDefer( elem, type, "queue" );
 1798+ }
13801799 }
13811800 });
13821801
@@ -1389,7 +1808,7 @@
13901809 if ( data === undefined ) {
13911810 return jQuery.queue( this[0], type );
13921811 }
1393 - return this.each(function( i ) {
 1812+ return this.each(function() {
13941813 var queue = jQuery.queue( this, type, data );
13951814
13961815 if ( type === "fx" && queue[0] !== "inprogress" ) {
@@ -1402,7 +1821,6 @@
14031822 jQuery.dequeue( this, type );
14041823 });
14051824 },
1406 -
14071825 // Based off of the plugin by Clint Helfers, with permission.
14081826 // http://blindsignals.com/index.php/2009/07/jquery-delay/
14091827 delay: function( time, type ) {
@@ -1416,61 +1834,93 @@
14171835 }, time );
14181836 });
14191837 },
1420 -
14211838 clearQueue: function( type ) {
14221839 return this.queue( type || "fx", [] );
 1840+ },
 1841+ // Get a promise resolved when queues of a certain type
 1842+ // are emptied (fx is the type by default)
 1843+ promise: function( type, object ) {
 1844+ if ( typeof type !== "string" ) {
 1845+ object = type;
 1846+ type = undefined;
 1847+ }
 1848+ type = type || "fx";
 1849+ var defer = jQuery.Deferred(),
 1850+ elements = this,
 1851+ i = elements.length,
 1852+ count = 1,
 1853+ deferDataKey = type + "defer",
 1854+ queueDataKey = type + "queue",
 1855+ markDataKey = type + "mark",
 1856+ tmp;
 1857+ function resolve() {
 1858+ if ( !( --count ) ) {
 1859+ defer.resolveWith( elements, [ elements ] );
 1860+ }
 1861+ }
 1862+ while( i-- ) {
 1863+ if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
 1864+ ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
 1865+ jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
 1866+ jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {
 1867+ count++;
 1868+ tmp.done( resolve );
 1869+ }
 1870+ }
 1871+ resolve();
 1872+ return defer.promise();
14231873 }
14241874 });
14251875
14261876
14271877
14281878
1429 -var rclass = /[\n\t]/g,
1430 - rspaces = /\s+/,
 1879+var rclass = /[\n\t\r]/g,
 1880+ rspace = /\s+/,
14311881 rreturn = /\r/g,
1432 - rspecialurl = /^(?:href|src|style)$/,
14331882 rtype = /^(?:button|input)$/i,
14341883 rfocusable = /^(?:button|input|object|select|textarea)$/i,
14351884 rclickable = /^a(?:rea)?$/i,
1436 - rradiocheck = /^(?:radio|checkbox)$/i;
 1885+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
 1886+ rinvalidChar = /\:/,
 1887+ formHook, boolHook;
14371888
1438 -jQuery.props = {
1439 - "for": "htmlFor",
1440 - "class": "className",
1441 - readonly: "readOnly",
1442 - maxlength: "maxLength",
1443 - cellspacing: "cellSpacing",
1444 - rowspan: "rowSpan",
1445 - colspan: "colSpan",
1446 - tabindex: "tabIndex",
1447 - usemap: "useMap",
1448 - frameborder: "frameBorder"
1449 -};
1450 -
14511889 jQuery.fn.extend({
14521890 attr: function( name, value ) {
14531891 return jQuery.access( this, name, value, true, jQuery.attr );
14541892 },
14551893
1456 - removeAttr: function( name, fn ) {
1457 - return this.each(function(){
1458 - jQuery.attr( this, name, "" );
1459 - if ( this.nodeType === 1 ) {
1460 - this.removeAttribute( name );
1461 - }
 1894+ removeAttr: function( name ) {
 1895+ return this.each(function() {
 1896+ jQuery.removeAttr( this, name );
14621897 });
14631898 },
 1899+
 1900+ prop: function( name, value ) {
 1901+ return jQuery.access( this, name, value, true, jQuery.prop );
 1902+ },
 1903+
 1904+ removeProp: function( name ) {
 1905+ name = jQuery.propFix[ name ] || name;
 1906+ return this.each(function() {
 1907+ // try/catch handles cases where IE balks (such as removing a property on window)
 1908+ try {
 1909+ this[ name ] = undefined;
 1910+ delete this[ name ];
 1911+ } catch( e ) {}
 1912+ });
 1913+ },
14641914
14651915 addClass: function( value ) {
1466 - if ( jQuery.isFunction(value) ) {
 1916+ if ( jQuery.isFunction( value ) ) {
14671917 return this.each(function(i) {
14681918 var self = jQuery(this);
1469 - self.addClass( value.call(this, i, self.attr("class")) );
 1919+ self.addClass( value.call(this, i, self.attr("class") || "") );
14701920 });
14711921 }
14721922
14731923 if ( value && typeof value === "string" ) {
1474 - var classNames = (value || "").split( rspaces );
 1924+ var classNames = (value || "").split( rspace );
14751925
14761926 for ( var i = 0, l = this.length; i < l; i++ ) {
14771927 var elem = this[i];
@@ -1506,7 +1956,7 @@
15071957 }
15081958
15091959 if ( (value && typeof value === "string") || value === undefined ) {
1510 - var classNames = (value || "").split( rspaces );
 1960+ var classNames = (value || "").split( rspace );
15111961
15121962 for ( var i = 0, l = this.length; i < l; i++ ) {
15131963 var elem = this[i];
@@ -1547,7 +1997,7 @@
15481998 i = 0,
15491999 self = jQuery( this ),
15502000 state = stateVal,
1551 - classNames = value.split( rspaces );
 2001+ classNames = value.split( rspace );
15522002
15532003 while ( (className = classNames[ i++ ]) ) {
15542004 // check each className given, space seperated list
@@ -1558,11 +2008,11 @@
15592009 } else if ( type === "undefined" || type === "boolean" ) {
15602010 if ( this.className ) {
15612011 // store className if set
1562 - jQuery.data( this, "__className__", this.className );
 2012+ jQuery._data( this, "__className__", this.className );
15632013 }
15642014
15652015 // toggle whole className
1566 - this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
 2016+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
15672017 }
15682018 });
15692019 },
@@ -1579,78 +2029,36 @@
15802030 },
15812031
15822032 val: function( value ) {
 2033+ var hooks, ret,
 2034+ elem = this[0];
 2035+
15832036 if ( !arguments.length ) {
1584 - var elem = this[0];
1585 -
15862037 if ( elem ) {
1587 - if ( jQuery.nodeName( elem, "option" ) ) {
1588 - // attributes.value is undefined in Blackberry 4.7 but
1589 - // uses .value. See #6932
1590 - var val = elem.attributes.value;
1591 - return !val || val.specified ? elem.value : elem.text;
1592 - }
 2038+ hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
15932039
1594 - // We need to handle select boxes special
1595 - if ( jQuery.nodeName( elem, "select" ) ) {
1596 - var index = elem.selectedIndex,
1597 - values = [],
1598 - options = elem.options,
1599 - one = elem.type === "select-one";
1600 -
1601 - // Nothing was selected
1602 - if ( index < 0 ) {
1603 - return null;
1604 - }
1605 -
1606 - // Loop through all the selected options
1607 - for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
1608 - var option = options[ i ];
1609 -
1610 - // Don't return options that are disabled or in a disabled optgroup
1611 - if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
1612 - (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
1613 -
1614 - // Get the specific value for the option
1615 - value = jQuery(option).val();
1616 -
1617 - // We don't need an array for one selects
1618 - if ( one ) {
1619 - return value;
1620 - }
1621 -
1622 - // Multi-Selects return an array
1623 - values.push( value );
1624 - }
1625 - }
1626 -
1627 - return values;
 2040+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
 2041+ return ret;
16282042 }
16292043
1630 - // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
1631 - if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
1632 - return elem.getAttribute("value") === null ? "on" : elem.value;
1633 - }
1634 -
1635 -
1636 - // Everything else, we just grab the value
16372044 return (elem.value || "").replace(rreturn, "");
1638 -
16392045 }
16402046
16412047 return undefined;
16422048 }
16432049
1644 - var isFunction = jQuery.isFunction(value);
 2050+ var isFunction = jQuery.isFunction( value );
16452051
1646 - return this.each(function(i) {
1647 - var self = jQuery(this), val = value;
 2052+ return this.each(function( i ) {
 2053+ var self = jQuery(this), val;
16482054
16492055 if ( this.nodeType !== 1 ) {
16502056 return;
16512057 }
16522058
16532059 if ( isFunction ) {
1654 - val = value.call(this, i, self.val());
 2060+ val = value.call( this, i, self.val() );
 2061+ } else {
 2062+ val = value;
16552063 }
16562064
16572065 // Treat null/undefined as ""; convert numbers to string
@@ -1658,34 +2066,89 @@
16592067 val = "";
16602068 } else if ( typeof val === "number" ) {
16612069 val += "";
1662 - } else if ( jQuery.isArray(val) ) {
1663 - val = jQuery.map(val, function (value) {
 2070+ } else if ( jQuery.isArray( val ) ) {
 2071+ val = jQuery.map(val, function ( value ) {
16642072 return value == null ? "" : value + "";
16652073 });
16662074 }
16672075
1668 - if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
1669 - this.checked = jQuery.inArray( self.val(), val ) >= 0;
 2076+ hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
16702077
1671 - } else if ( jQuery.nodeName( this, "select" ) ) {
1672 - var values = jQuery.makeArray(val);
 2078+ // If set returns undefined, fall back to normal setting
 2079+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
 2080+ this.value = val;
 2081+ }
 2082+ });
 2083+ }
 2084+});
16732085
1674 - jQuery( "option", this ).each(function() {
 2086+jQuery.extend({
 2087+ valHooks: {
 2088+ option: {
 2089+ get: function( elem ) {
 2090+ // attributes.value is undefined in Blackberry 4.7 but
 2091+ // uses .value. See #6932
 2092+ var val = elem.attributes.value;
 2093+ return !val || val.specified ? elem.value : elem.text;
 2094+ }
 2095+ },
 2096+ select: {
 2097+ get: function( elem ) {
 2098+ var value,
 2099+ index = elem.selectedIndex,
 2100+ values = [],
 2101+ options = elem.options,
 2102+ one = elem.type === "select-one";
 2103+
 2104+ // Nothing was selected
 2105+ if ( index < 0 ) {
 2106+ return null;
 2107+ }
 2108+
 2109+ // Loop through all the selected options
 2110+ for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
 2111+ var option = options[ i ];
 2112+
 2113+ // Don't return options that are disabled or in a disabled optgroup
 2114+ if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
 2115+ (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
 2116+
 2117+ // Get the specific value for the option
 2118+ value = jQuery( option ).val();
 2119+
 2120+ // We don't need an array for one selects
 2121+ if ( one ) {
 2122+ return value;
 2123+ }
 2124+
 2125+ // Multi-Selects return an array
 2126+ values.push( value );
 2127+ }
 2128+ }
 2129+
 2130+ // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
 2131+ if ( one && !values.length && options.length ) {
 2132+ return jQuery( options[ index ] ).val();
 2133+ }
 2134+
 2135+ return values;
 2136+ },
 2137+
 2138+ set: function( elem, value ) {
 2139+ var values = jQuery.makeArray( value );
 2140+
 2141+ jQuery(elem).find("option").each(function() {
16752142 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
16762143 });
16772144
16782145 if ( !values.length ) {
1679 - this.selectedIndex = -1;
 2146+ elem.selectedIndex = -1;
16802147 }
1681 -
1682 - } else {
1683 - this.value = val;
 2148+ return values;
16842149 }
1685 - });
1686 - }
1687 -});
 2150+ }
 2151+ },
16882152
1689 -jQuery.extend({
16902153 attrFn: {
16912154 val: true,
16922155 css: true,
@@ -1696,121 +2159,349 @@
16972160 height: true,
16982161 offset: true
16992162 },
 2163+
 2164+ attrFix: {
 2165+ // Always normalize to ensure hook usage
 2166+ tabindex: "tabIndex"
 2167+ },
 2168+
 2169+ attr: function( elem, name, value, pass ) {
 2170+ var nType = elem.nodeType;
17002171
1701 - attr: function( elem, name, value, pass ) {
1702 - // don't set attributes on text and comment nodes
1703 - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
 2172+ // don't get/set attributes on text, comment and attribute nodes
 2173+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
17042174 return undefined;
17052175 }
17062176
17072177 if ( pass && name in jQuery.attrFn ) {
1708 - return jQuery(elem)[name](value);
 2178+ return jQuery( elem )[ name ]( value );
17092179 }
17102180
1711 - var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
1712 - // Whether we are setting (or getting)
1713 - set = value !== undefined;
 2181+ // Fallback to prop when attributes are not supported
 2182+ if ( !("getAttribute" in elem) ) {
 2183+ return jQuery.prop( elem, name, value );
 2184+ }
17142185
1715 - // Try to normalize/fix the name
1716 - name = notxml && jQuery.props[ name ] || name;
 2186+ var ret, hooks,
 2187+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
17172188
1718 - // These attributes require special treatment
1719 - var special = rspecialurl.test( name );
 2189+ // Normalize the name if needed
 2190+ name = notxml && jQuery.attrFix[ name ] || name;
17202191
1721 - // Safari mis-reports the default selected property of an option
1722 - // Accessing the parent's selectedIndex property fixes it
1723 - if ( name === "selected" && !jQuery.support.optSelected ) {
1724 - var parent = elem.parentNode;
1725 - if ( parent ) {
1726 - parent.selectedIndex;
 2192+ hooks = jQuery.attrHooks[ name ];
17272193
1728 - // Make sure that it also works with optgroups, see #5701
1729 - if ( parent.parentNode ) {
1730 - parent.parentNode.selectedIndex;
1731 - }
 2194+ if ( !hooks ) {
 2195+ // Use boolHook for boolean attributes
 2196+ if ( rboolean.test( name ) &&
 2197+ (typeof value === "boolean" || value === undefined || value.toLowerCase() === name.toLowerCase()) ) {
 2198+
 2199+ hooks = boolHook;
 2200+
 2201+ // Use formHook for forms and if the name contains certain characters
 2202+ } else if ( formHook && (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) {
 2203+ hooks = formHook;
17322204 }
17332205 }
17342206
1735 - // If applicable, access the attribute via the DOM 0 way
1736 - // 'in' checks fail in Blackberry 4.7 #6931
1737 - if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) {
1738 - if ( set ) {
1739 - // We can't allow the type property to be changed (since it causes problems in IE)
1740 - if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
1741 - jQuery.error( "type property can't be changed" );
1742 - }
 2207+ if ( value !== undefined ) {
17432208
1744 - if ( value === null ) {
1745 - if ( elem.nodeType === 1 ) {
1746 - elem.removeAttribute( name );
1747 - }
 2209+ if ( value === null ) {
 2210+ jQuery.removeAttr( elem, name );
 2211+ return undefined;
17482212
1749 - } else {
1750 - elem[ name ] = value;
1751 - }
 2213+ } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
 2214+ return ret;
 2215+
 2216+ } else {
 2217+ elem.setAttribute( name, "" + value );
 2218+ return value;
17522219 }
17532220
1754 - // browsers index elements by id/name on forms, give priority to attributes.
1755 - if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
1756 - return elem.getAttributeNode( name ).nodeValue;
 2221+ } else if ( hooks && "get" in hooks && notxml ) {
 2222+ return hooks.get( elem, name );
 2223+
 2224+ } else {
 2225+
 2226+ ret = elem.getAttribute( name );
 2227+
 2228+ // Non-existent attributes return null, we normalize to undefined
 2229+ return ret === null ?
 2230+ undefined :
 2231+ ret;
 2232+ }
 2233+ },
 2234+
 2235+ removeAttr: function( elem, name ) {
 2236+ var propName;
 2237+ if ( elem.nodeType === 1 ) {
 2238+ name = jQuery.attrFix[ name ] || name;
 2239+
 2240+ if ( jQuery.support.getSetAttribute ) {
 2241+ // Use removeAttribute in browsers that support it
 2242+ elem.removeAttribute( name );
 2243+ } else {
 2244+ jQuery.attr( elem, name, "" );
 2245+ elem.removeAttributeNode( elem.getAttributeNode( name ) );
17572246 }
17582247
1759 - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
1760 - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
1761 - if ( name === "tabIndex" ) {
1762 - var attributeNode = elem.getAttributeNode( "tabIndex" );
 2248+ // Set corresponding property to false for boolean attributes
 2249+ if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) {
 2250+ elem[ propName ] = false;
 2251+ }
 2252+ }
 2253+ },
17632254
 2255+ attrHooks: {
 2256+ type: {
 2257+ set: function( elem, value ) {
 2258+ // We can't allow the type property to be changed (since it causes problems in IE)
 2259+ if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
 2260+ jQuery.error( "type property can't be changed" );
 2261+ } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
 2262+ // Setting the type on a radio button after the value resets the value in IE6-9
 2263+ // Reset value to it's default in case type is set after value
 2264+ // This is for element creation
 2265+ var val = elem.value;
 2266+ elem.setAttribute( "type", value );
 2267+ if ( val ) {
 2268+ elem.value = val;
 2269+ }
 2270+ return value;
 2271+ }
 2272+ }
 2273+ },
 2274+ tabIndex: {
 2275+ get: function( elem ) {
 2276+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
 2277+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
 2278+ var attributeNode = elem.getAttributeNode("tabIndex");
 2279+
17642280 return attributeNode && attributeNode.specified ?
1765 - attributeNode.value :
 2281+ parseInt( attributeNode.value, 10 ) :
17662282 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
17672283 0 :
17682284 undefined;
17692285 }
 2286+ }
 2287+ },
17702288
1771 - return elem[ name ];
 2289+ propFix: {
 2290+ tabindex: "tabIndex",
 2291+ readonly: "readOnly",
 2292+ "for": "htmlFor",
 2293+ "class": "className",
 2294+ maxlength: "maxLength",
 2295+ cellspacing: "cellSpacing",
 2296+ cellpadding: "cellPadding",
 2297+ rowspan: "rowSpan",
 2298+ colspan: "colSpan",
 2299+ usemap: "useMap",
 2300+ frameborder: "frameBorder",
 2301+ contenteditable: "contentEditable"
 2302+ },
 2303+
 2304+ prop: function( elem, name, value ) {
 2305+ var nType = elem.nodeType;
 2306+
 2307+ // don't get/set properties on text, comment and attribute nodes
 2308+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
 2309+ return undefined;
17722310 }
17732311
1774 - if ( !jQuery.support.style && notxml && name === "style" ) {
1775 - if ( set ) {
1776 - elem.style.cssText = "" + value;
 2312+ var ret, hooks,
 2313+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
 2314+
 2315+ // Try to normalize/fix the name
 2316+ name = notxml && jQuery.propFix[ name ] || name;
 2317+
 2318+ hooks = jQuery.propHooks[ name ];
 2319+
 2320+ if ( value !== undefined ) {
 2321+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
 2322+ return ret;
 2323+
 2324+ } else {
 2325+ return (elem[ name ] = value);
17772326 }
17782327
1779 - return elem.style.cssText;
 2328+ } else {
 2329+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {
 2330+ return ret;
 2331+
 2332+ } else {
 2333+ return elem[ name ];
 2334+ }
17802335 }
 2336+ },
 2337+
 2338+ propHooks: {}
 2339+});
17812340
1782 - if ( set ) {
1783 - // convert the value to a string (all browsers do this but IE) see #1070
1784 - elem.setAttribute( name, "" + value );
 2341+// Hook for boolean attributes
 2342+boolHook = {
 2343+ get: function( elem, name ) {
 2344+ // Align boolean attributes with corresponding properties
 2345+ return elem[ jQuery.propFix[ name ] || name ] ?
 2346+ name.toLowerCase() :
 2347+ undefined;
 2348+ },
 2349+ set: function( elem, value, name ) {
 2350+ var propName;
 2351+ if ( value === false ) {
 2352+ // Remove boolean attributes when set to false
 2353+ jQuery.removeAttr( elem, name );
 2354+ } else {
 2355+ // value is true since we know at this point it's type boolean and not false
 2356+ // Set boolean attributes to the same name and set the DOM property
 2357+ propName = jQuery.propFix[ name ] || name;
 2358+ if ( propName in elem ) {
 2359+ // Only set the IDL specifically if it already exists on the element
 2360+ elem[ propName ] = value;
 2361+ }
 2362+
 2363+ elem.setAttribute( name, name.toLowerCase() );
17852364 }
 2365+ return name;
 2366+ }
 2367+};
17862368
1787 - // Ensure that missing attributes return undefined
1788 - // Blackberry 4.7 returns "" from getAttribute #6938
1789 - if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) {
1790 - return undefined;
 2369+// Use the value property for back compat
 2370+// Use the formHook for button elements in IE6/7 (#1954)
 2371+jQuery.attrHooks.value = {
 2372+ get: function( elem, name ) {
 2373+ if ( formHook && jQuery.nodeName( elem, "button" ) ) {
 2374+ return formHook.get( elem, name );
17912375 }
 2376+ return elem.value;
 2377+ },
 2378+ set: function( elem, value, name ) {
 2379+ if ( formHook && jQuery.nodeName( elem, "button" ) ) {
 2380+ return formHook.set( elem, value, name );
 2381+ }
 2382+ // Does not return so that setAttribute is also used
 2383+ elem.value = value;
 2384+ }
 2385+};
17922386
1793 - var attr = !jQuery.support.hrefNormalized && notxml && special ?
1794 - // Some attributes require a special call on IE
1795 - elem.getAttribute( name, 2 ) :
1796 - elem.getAttribute( name );
 2387+// IE6/7 do not support getting/setting some attributes with get/setAttribute
 2388+if ( !jQuery.support.getSetAttribute ) {
17972389
1798 - // Non-existent attributes return null, we normalize to undefined
1799 - return attr === null ? undefined : attr;
1800 - }
 2390+ // propFix is more comprehensive and contains all fixes
 2391+ jQuery.attrFix = jQuery.propFix;
 2392+
 2393+ // Use this for any attribute on a form in IE6/7
 2394+ formHook = jQuery.attrHooks.name = jQuery.valHooks.button = {
 2395+ get: function( elem, name ) {
 2396+ var ret;
 2397+ ret = elem.getAttributeNode( name );
 2398+ // Return undefined if nodeValue is empty string
 2399+ return ret && ret.nodeValue !== "" ?
 2400+ ret.nodeValue :
 2401+ undefined;
 2402+ },
 2403+ set: function( elem, value, name ) {
 2404+ // Check form objects in IE (multiple bugs related)
 2405+ // Only use nodeValue if the attribute node exists on the form
 2406+ var ret = elem.getAttributeNode( name );
 2407+ if ( ret ) {
 2408+ ret.nodeValue = value;
 2409+ return value;
 2410+ }
 2411+ }
 2412+ };
 2413+
 2414+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
 2415+ // This is for removals
 2416+ jQuery.each([ "width", "height" ], function( i, name ) {
 2417+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
 2418+ set: function( elem, value ) {
 2419+ if ( value === "" ) {
 2420+ elem.setAttribute( name, "auto" );
 2421+ return value;
 2422+ }
 2423+ }
 2424+ });
 2425+ });
 2426+}
 2427+
 2428+
 2429+// Some attributes require a special call on IE
 2430+if ( !jQuery.support.hrefNormalized ) {
 2431+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
 2432+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
 2433+ get: function( elem ) {
 2434+ var ret = elem.getAttribute( name, 2 );
 2435+ return ret === null ? undefined : ret;
 2436+ }
 2437+ });
 2438+ });
 2439+}
 2440+
 2441+if ( !jQuery.support.style ) {
 2442+ jQuery.attrHooks.style = {
 2443+ get: function( elem ) {
 2444+ // Return undefined in the case of empty string
 2445+ // Normalize to lowercase since IE uppercases css property names
 2446+ return elem.style.cssText.toLowerCase() || undefined;
 2447+ },
 2448+ set: function( elem, value ) {
 2449+ return (elem.style.cssText = "" + value);
 2450+ }
 2451+ };
 2452+}
 2453+
 2454+// Safari mis-reports the default selected property of an option
 2455+// Accessing the parent's selectedIndex property fixes it
 2456+if ( !jQuery.support.optSelected ) {
 2457+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
 2458+ get: function( elem ) {
 2459+ var parent = elem.parentNode;
 2460+
 2461+ if ( parent ) {
 2462+ parent.selectedIndex;
 2463+
 2464+ // Make sure that it also works with optgroups, see #5701
 2465+ if ( parent.parentNode ) {
 2466+ parent.parentNode.selectedIndex;
 2467+ }
 2468+ }
 2469+ }
 2470+ });
 2471+}
 2472+
 2473+// Radios and checkboxes getter/setter
 2474+if ( !jQuery.support.checkOn ) {
 2475+ jQuery.each([ "radio", "checkbox" ], function() {
 2476+ jQuery.valHooks[ this ] = {
 2477+ get: function( elem ) {
 2478+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
 2479+ return elem.getAttribute("value") === null ? "on" : elem.value;
 2480+ }
 2481+ };
 2482+ });
 2483+}
 2484+jQuery.each([ "radio", "checkbox" ], function() {
 2485+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
 2486+ set: function( elem, value ) {
 2487+ if ( jQuery.isArray( value ) ) {
 2488+ return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);
 2489+ }
 2490+ }
 2491+ });
18012492 });
18022493
18032494
18042495
18052496
1806 -var rnamespaces = /\.(.*)$/,
 2497+var hasOwn = Object.prototype.hasOwnProperty,
 2498+ rnamespaces = /\.(.*)$/,
18072499 rformElems = /^(?:textarea|input|select)$/i,
18082500 rperiod = /\./g,
1809 - rspace = / /g,
 2501+ rspaces = / /g,
18102502 rescape = /[^\w\s.|`]/g,
18112503 fcleanup = function( nm ) {
18122504 return nm.replace(rescape, "\\$&");
1813 - },
1814 - focusCounts = { focusin: 0, focusout: 0 };
 2505+ };
18152506
18162507 /*
18172508 * A number of helper functions used for managing events.
@@ -1826,17 +2517,11 @@
18272518 return;
18282519 }
18292520
1830 - // For whatever reason, IE has trouble passing the window object
1831 - // around, causing it to be cloned in the process
1832 - if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
1833 - elem = window;
1834 - }
1835 -
18362521 if ( handler === false ) {
18372522 handler = returnFalse;
18382523 } else if ( !handler ) {
18392524 // Fixes bug #7229. Fix recommended by jdalton
1840 - return;
 2525+ return;
18412526 }
18422527
18432528 var handleObjIn, handleObj;
@@ -1852,7 +2537,7 @@
18532538 }
18542539
18552540 // Init the element's event structure
1856 - var elemData = jQuery.data( elem );
 2541+ var elemData = jQuery._data( elem );
18572542
18582543 // If no elemData is found then we must be trying to bind to one of the
18592544 // banned noData elements
@@ -1860,34 +2545,18 @@
18612546 return;
18622547 }
18632548
1864 - // Use a key less likely to result in collisions for plain JS objects.
1865 - // Fixes bug #7150.
1866 - var eventKey = elem.nodeType ? "events" : "__events__",
1867 - events = elemData[ eventKey ],
 2549+ var events = elemData.events,
18682550 eventHandle = elemData.handle;
1869 -
1870 - if ( typeof events === "function" ) {
1871 - // On plain objects events is a fn that holds the the data
1872 - // which prevents this data from being JSON serialized
1873 - // the function does not need to be called, it just contains the data
1874 - eventHandle = events.handle;
1875 - events = events.events;
18762551
1877 - } else if ( !events ) {
1878 - if ( !elem.nodeType ) {
1879 - // On plain objects, create a fn that acts as the holder
1880 - // of the values to avoid JSON serialization of event data
1881 - elemData[ eventKey ] = elemData = function(){};
1882 - }
1883 -
 2552+ if ( !events ) {
18842553 elemData.events = events = {};
18852554 }
18862555
18872556 if ( !eventHandle ) {
1888 - elemData.handle = eventHandle = function() {
1889 - // Handle the second event of a trigger and when
1890 - // an event is called after a page has unloaded
1891 - return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
 2557+ elemData.handle = eventHandle = function( e ) {
 2558+ // Discard the second event of a jQuery.event.trigger() and
 2559+ // when an event is called after a page has unloaded
 2560+ return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
18922561 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
18932562 undefined;
18942563 };
@@ -1945,10 +2614,10 @@
19462615 }
19472616 }
19482617 }
1949 -
1950 - if ( special.add ) {
1951 - special.add.call( elem, handleObj );
19522618
 2619+ if ( special.add ) {
 2620+ special.add.call( elem, handleObj );
 2621+
19532622 if ( !handleObj.handler.guid ) {
19542623 handleObj.handler.guid = handler.guid;
19552624 }
@@ -1957,7 +2626,7 @@
19582627 // Add the function to the element's handler list
19592628 handlers.push( handleObj );
19602629
1961 - // Keep track of which events have been used, for global triggering
 2630+ // Keep track of which events have been used, for event optimization
19622631 jQuery.event.global[ type ] = true;
19632632 }
19642633
@@ -1979,18 +2648,12 @@
19802649 }
19812650
19822651 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
1983 - eventKey = elem.nodeType ? "events" : "__events__",
1984 - elemData = jQuery.data( elem ),
1985 - events = elemData && elemData[ eventKey ];
 2652+ elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
 2653+ events = elemData && elemData.events;
19862654
19872655 if ( !elemData || !events ) {
19882656 return;
19892657 }
1990 -
1991 - if ( typeof events === "function" ) {
1992 - elemData = events;
1993 - events = events.events;
1994 - }
19952658
19962659 // types is actually an event object here
19972660 if ( types && types.type ) {
@@ -2024,7 +2687,7 @@
20252688 namespaces = type.split(".");
20262689 type = namespaces.shift();
20272690
2028 - namespace = new RegExp("(^|\\.)" +
 2691+ namespace = new RegExp("(^|\\.)" +
20292692 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
20302693 }
20312694
@@ -2091,189 +2754,190 @@
20922755 delete elemData.events;
20932756 delete elemData.handle;
20942757
2095 - if ( typeof elemData === "function" ) {
2096 - jQuery.removeData( elem, eventKey );
2097 -
2098 - } else if ( jQuery.isEmptyObject( elemData ) ) {
2099 - jQuery.removeData( elem );
 2758+ if ( jQuery.isEmptyObject( elemData ) ) {
 2759+ jQuery.removeData( elem, undefined, true );
21002760 }
21012761 }
21022762 },
 2763+
 2764+ // Events that are safe to short-circuit if no handlers are attached.
 2765+ // Native DOM events should not be added, they may have inline handlers.
 2766+ customEvent: {
 2767+ "getData": true,
 2768+ "setData": true,
 2769+ "changeData": true
 2770+ },
21032771
2104 - // bubbling is internal
2105 - trigger: function( event, data, elem /*, bubbling */ ) {
 2772+ trigger: function( event, data, elem, onlyHandlers ) {
21062773 // Event object or event type
21072774 var type = event.type || event,
2108 - bubbling = arguments[3];
 2775+ namespaces = [],
 2776+ exclusive;
21092777
2110 - if ( !bubbling ) {
2111 - event = typeof event === "object" ?
2112 - // jQuery.Event object
2113 - event[ jQuery.expando ] ? event :
2114 - // Object literal
2115 - jQuery.extend( jQuery.Event(type), event ) :
2116 - // Just the event type (string)
2117 - jQuery.Event(type);
 2778+ if ( type.indexOf("!") >= 0 ) {
 2779+ // Exclusive events trigger only for the exact event (no namespaces)
 2780+ type = type.slice(0, -1);
 2781+ exclusive = true;
 2782+ }
21182783
2119 - if ( type.indexOf("!") >= 0 ) {
2120 - event.type = type = type.slice(0, -1);
2121 - event.exclusive = true;
2122 - }
 2784+ if ( type.indexOf(".") >= 0 ) {
 2785+ // Namespaced trigger; create a regexp to match event type in handle()
 2786+ namespaces = type.split(".");
 2787+ type = namespaces.shift();
 2788+ namespaces.sort();
 2789+ }
21232790
2124 - // Handle a global trigger
2125 - if ( !elem ) {
2126 - // Don't bubble custom events when global (to avoid too much overhead)
2127 - event.stopPropagation();
 2791+ if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
 2792+ // No jQuery handlers for this event type, and it can't have inline handlers
 2793+ return;
 2794+ }
21282795
2129 - // Only trigger if we've ever bound an event for it
2130 - if ( jQuery.event.global[ type ] ) {
2131 - jQuery.each( jQuery.cache, function() {
2132 - if ( this.events && this.events[type] ) {
2133 - jQuery.event.trigger( event, data, this.handle.elem );
2134 - }
2135 - });
2136 - }
2137 - }
 2796+ // Caller can pass in an Event, Object, or just an event type string
 2797+ event = typeof event === "object" ?
 2798+ // jQuery.Event object
 2799+ event[ jQuery.expando ] ? event :
 2800+ // Object literal
 2801+ new jQuery.Event( type, event ) :
 2802+ // Just the event type (string)
 2803+ new jQuery.Event( type );
21382804
2139 - // Handle triggering a single element
 2805+ event.type = type;
 2806+ event.exclusive = exclusive;
 2807+ event.namespace = namespaces.join(".");
 2808+ event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)");
 2809+
 2810+ // triggerHandler() and global events don't bubble or run the default action
 2811+ if ( onlyHandlers || !elem ) {
 2812+ event.preventDefault();
 2813+ event.stopPropagation();
 2814+ }
21402815
2141 - // don't do events on text and comment nodes
2142 - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
2143 - return undefined;
2144 - }
 2816+ // Handle a global trigger
 2817+ if ( !elem ) {
 2818+ // TODO: Stop taunting the data cache; remove global events and always attach to document
 2819+ jQuery.each( jQuery.cache, function() {
 2820+ // internalKey variable is just used to make it easier to find
 2821+ // and potentially change this stuff later; currently it just
 2822+ // points to jQuery.expando
 2823+ var internalKey = jQuery.expando,
 2824+ internalCache = this[ internalKey ];
 2825+ if ( internalCache && internalCache.events && internalCache.events[ type ] ) {
 2826+ jQuery.event.trigger( event, data, internalCache.handle.elem );
 2827+ }
 2828+ });
 2829+ return;
 2830+ }
21452831
2146 - // Clean up in case it is reused
2147 - event.result = undefined;
2148 - event.target = elem;
2149 -
2150 - // Clone the incoming data, if any
2151 - data = jQuery.makeArray( data );
2152 - data.unshift( event );
 2832+ // Don't do events on text and comment nodes
 2833+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
 2834+ return;
21532835 }
21542836
2155 - event.currentTarget = elem;
 2837+ // Clean up the event in case it is being reused
 2838+ event.result = undefined;
 2839+ event.target = elem;
21562840
2157 - // Trigger the event, it is assumed that "handle" is a function
2158 - var handle = elem.nodeType ?
2159 - jQuery.data( elem, "handle" ) :
2160 - (jQuery.data( elem, "__events__" ) || {}).handle;
 2841+ // Clone any incoming data and prepend the event, creating the handler arg list
 2842+ data = data ? jQuery.makeArray( data ) : [];
 2843+ data.unshift( event );
21612844
2162 - if ( handle ) {
2163 - handle.apply( elem, data );
2164 - }
 2845+ var cur = elem,
 2846+ // IE doesn't like method names with a colon (#3533, #8272)
 2847+ ontype = type.indexOf(":") < 0 ? "on" + type : "";
21652848
2166 - var parent = elem.parentNode || elem.ownerDocument;
 2849+ // Fire event on the current element, then bubble up the DOM tree
 2850+ do {
 2851+ var handle = jQuery._data( cur, "handle" );
21672852
2168 - // Trigger an inline bound script
2169 - try {
2170 - if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
2171 - if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
2172 - event.result = false;
2173 - event.preventDefault();
2174 - }
 2853+ event.currentTarget = cur;
 2854+ if ( handle ) {
 2855+ handle.apply( cur, data );
21752856 }
21762857
2177 - // prevent IE from throwing an error for some elements with some event types, see #3533
2178 - } catch (inlineError) {}
 2858+ // Trigger an inline bound script
 2859+ if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {
 2860+ event.result = false;
 2861+ event.preventDefault();
 2862+ }
21792863
2180 - if ( !event.isPropagationStopped() && parent ) {
2181 - jQuery.event.trigger( event, data, parent, true );
 2864+ // Bubble up to document, then to window
 2865+ cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;
 2866+ } while ( cur && !event.isPropagationStopped() );
21822867
2183 - } else if ( !event.isDefaultPrevented() ) {
 2868+ // If nobody prevented the default action, do it now
 2869+ if ( !event.isDefaultPrevented() ) {
21842870 var old,
2185 - target = event.target,
2186 - targetType = type.replace( rnamespaces, "" ),
2187 - isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
2188 - special = jQuery.event.special[ targetType ] || {};
 2871+ special = jQuery.event.special[ type ] || {};
21892872
2190 - if ( (!special._default || special._default.call( elem, event ) === false) &&
2191 - !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
 2873+ if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&
 2874+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
21922875
 2876+ // Call a native DOM method on the target with the same name name as the event.
 2877+ // Can't use an .isFunction)() check here because IE6/7 fails that test.
 2878+ // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.
21932879 try {
2194 - if ( target[ targetType ] ) {
2195 - // Make sure that we don't accidentally re-trigger the onFOO events
2196 - old = target[ "on" + targetType ];
 2880+ if ( ontype && elem[ type ] ) {
 2881+ // Don't re-trigger an onFOO event when we call its FOO() method
 2882+ old = elem[ ontype ];
21972883
21982884 if ( old ) {
2199 - target[ "on" + targetType ] = null;
 2885+ elem[ ontype ] = null;
22002886 }
22012887
2202 - jQuery.event.triggered = true;
2203 - target[ targetType ]();
 2888+ jQuery.event.triggered = type;
 2889+ elem[ type ]();
22042890 }
 2891+ } catch ( ieError ) {}
22052892
2206 - // prevent IE from throwing an error for some elements with some event types, see #3533
2207 - } catch (triggerError) {}
2208 -
22092893 if ( old ) {
2210 - target[ "on" + targetType ] = old;
 2894+ elem[ ontype ] = old;
22112895 }
22122896
2213 - jQuery.event.triggered = false;
 2897+ jQuery.event.triggered = undefined;
22142898 }
22152899 }
 2900+
 2901+ return event.result;
22162902 },
22172903
22182904 handle: function( event ) {
2219 - var all, handlers, namespaces, namespace_re, events,
2220 - namespace_sort = [],
2221 - args = jQuery.makeArray( arguments );
 2905+ event = jQuery.event.fix( event || window.event );
 2906+ // Snapshot the handlers list since a called handler may add/remove events.
 2907+ var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0),
 2908+ run_all = !event.exclusive && !event.namespace,
 2909+ args = Array.prototype.slice.call( arguments, 0 );
22222910
2223 - event = args[0] = jQuery.event.fix( event || window.event );
 2911+ // Use the fix-ed Event rather than the (read-only) native event
 2912+ args[0] = event;
22242913 event.currentTarget = this;
22252914
2226 - // Namespaced event handlers
2227 - all = event.type.indexOf(".") < 0 && !event.exclusive;
 2915+ for ( var j = 0, l = handlers.length; j < l; j++ ) {
 2916+ var handleObj = handlers[ j ];
22282917
2229 - if ( !all ) {
2230 - namespaces = event.type.split(".");
2231 - event.type = namespaces.shift();
2232 - namespace_sort = namespaces.slice(0).sort();
2233 - namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
2234 - }
 2918+ // Triggered event must 1) be non-exclusive and have no namespace, or
 2919+ // 2) have namespace(s) a subset or equal to those in the bound event.
 2920+ if ( run_all || event.namespace_re.test( handleObj.namespace ) ) {
 2921+ // Pass in a reference to the handler function itself
 2922+ // So that we can later remove it
 2923+ event.handler = handleObj.handler;
 2924+ event.data = handleObj.data;
 2925+ event.handleObj = handleObj;
22352926
2236 - event.namespace = event.namespace || namespace_sort.join(".");
 2927+ var ret = handleObj.handler.apply( this, args );
22372928
2238 - events = jQuery.data(this, this.nodeType ? "events" : "__events__");
2239 -
2240 - if ( typeof events === "function" ) {
2241 - events = events.events;
2242 - }
2243 -
2244 - handlers = (events || {})[ event.type ];
2245 -
2246 - if ( events && handlers ) {
2247 - // Clone the handlers to prevent manipulation
2248 - handlers = handlers.slice(0);
2249 -
2250 - for ( var j = 0, l = handlers.length; j < l; j++ ) {
2251 - var handleObj = handlers[ j ];
2252 -
2253 - // Filter the functions by class
2254 - if ( all || namespace_re.test( handleObj.namespace ) ) {
2255 - // Pass in a reference to the handler function itself
2256 - // So that we can later remove it
2257 - event.handler = handleObj.handler;
2258 - event.data = handleObj.data;
2259 - event.handleObj = handleObj;
2260 -
2261 - var ret = handleObj.handler.apply( this, args );
2262 -
2263 - if ( ret !== undefined ) {
2264 - event.result = ret;
2265 - if ( ret === false ) {
2266 - event.preventDefault();
2267 - event.stopPropagation();
2268 - }
 2929+ if ( ret !== undefined ) {
 2930+ event.result = ret;
 2931+ if ( ret === false ) {
 2932+ event.preventDefault();
 2933+ event.stopPropagation();
22692934 }
 2935+ }
22702936
2271 - if ( event.isImmediatePropagationStopped() ) {
2272 - break;
2273 - }
 2937+ if ( event.isImmediatePropagationStopped() ) {
 2938+ break;
22742939 }
22752940 }
22762941 }
2277 -
22782942 return event.result;
22792943 },
22802944
@@ -2312,8 +2976,9 @@
23132977
23142978 // Calculate pageX/Y if missing and clientX/Y available
23152979 if ( event.pageX == null && event.clientX != null ) {
2316 - var doc = document.documentElement,
2317 - body = document.body;
 2980+ var eventDocument = event.target.ownerDocument || document,
 2981+ doc = eventDocument.documentElement,
 2982+ body = eventDocument.body;
23182983
23192984 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
23202985 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
@@ -2355,7 +3020,7 @@
23563021 add: function( handleObj ) {
23573022 jQuery.event.add( this,
23583023 liveConvert( handleObj.origType, handleObj.selector ),
2359 - jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
 3024+ jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
23603025 },
23613026
23623027 remove: function( handleObj ) {
@@ -2385,28 +3050,39 @@
23863051 if ( elem.removeEventListener ) {
23873052 elem.removeEventListener( type, handle, false );
23883053 }
2389 - } :
 3054+ } :
23903055 function( elem, type, handle ) {
23913056 if ( elem.detachEvent ) {
23923057 elem.detachEvent( "on" + type, handle );
23933058 }
23943059 };
23953060
2396 -jQuery.Event = function( src ) {
 3061+jQuery.Event = function( src, props ) {
23973062 // Allow instantiation without the 'new' keyword
23983063 if ( !this.preventDefault ) {
2399 - return new jQuery.Event( src );
 3064+ return new jQuery.Event( src, props );
24003065 }
24013066
24023067 // Event object
24033068 if ( src && src.type ) {
24043069 this.originalEvent = src;
24053070 this.type = src.type;
 3071+
 3072+ // Events bubbling up the document may have been marked as prevented
 3073+ // by a handler lower down the tree; reflect the correct value.
 3074+ this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
 3075+ src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
 3076+
24063077 // Event type
24073078 } else {
24083079 this.type = src;
24093080 }
24103081
 3082+ // Put explicitly provided properties onto the event object
 3083+ if ( props ) {
 3084+ jQuery.extend( this, props );
 3085+ }
 3086+
24113087 // timeStamp is buggy for some events on Firefox(#3843)
24123088 // So we won't rely on the native value
24133089 this.timeStamp = jQuery.now();
@@ -2432,7 +3108,7 @@
24333109 if ( !e ) {
24343110 return;
24353111 }
2436 -
 3112+
24373113 // if preventDefault exists run it on the original event
24383114 if ( e.preventDefault ) {
24393115 e.preventDefault();
@@ -2471,18 +3147,25 @@
24723148 // Check if mouse(over|out) are still within the same parent element
24733149 var parent = event.relatedTarget;
24743150
 3151+ // set the correct event type
 3152+ event.type = event.data;
 3153+
24753154 // Firefox sometimes assigns relatedTarget a XUL element
24763155 // which we cannot access the parentNode property of
24773156 try {
 3157+
 3158+ // Chrome does something similar, the parentNode property
 3159+ // can be accessed but is null.
 3160+ if ( parent && parent !== document && !parent.parentNode ) {
 3161+ return;
 3162+ }
 3163+
24783164 // Traverse up the tree
24793165 while ( parent && parent !== this ) {
24803166 parent = parent.parentNode;
24813167 }
24823168
24833169 if ( parent !== this ) {
2484 - // set the correct event type
2485 - event.type = event.data;
2486 -
24873170 // handle event if we actually just moused on to a non sub-element
24883171 jQuery.event.handle.apply( this, arguments );
24893172 }
@@ -2518,24 +3201,22 @@
25193202
25203203 jQuery.event.special.submit = {
25213204 setup: function( data, namespaces ) {
2522 - if ( this.nodeName.toLowerCase() !== "form" ) {
 3205+ if ( !jQuery.nodeName( this, "form" ) ) {
25233206 jQuery.event.add(this, "click.specialSubmit", function( e ) {
25243207 var elem = e.target,
25253208 type = elem.type;
25263209
25273210 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
2528 - e.liveFired = undefined;
2529 - return trigger( "submit", this, arguments );
 3211+ trigger( "submit", this, arguments );
25303212 }
25313213 });
2532 -
 3214+
25333215 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
25343216 var elem = e.target,
25353217 type = elem.type;
25363218
25373219 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
2538 - e.liveFired = undefined;
2539 - return trigger( "submit", this, arguments );
 3220+ trigger( "submit", this, arguments );
25403221 }
25413222 });
25423223
@@ -2569,7 +3250,7 @@
25703251 }).join("-") :
25713252 "";
25723253
2573 - } else if ( elem.nodeName.toLowerCase() === "select" ) {
 3254+ } else if ( jQuery.nodeName( elem, "select" ) ) {
25743255 val = elem.selectedIndex;
25753256 }
25763257
@@ -2583,14 +3264,14 @@
25843265 return;
25853266 }
25863267
2587 - data = jQuery.data( elem, "_change_data" );
 3268+ data = jQuery._data( elem, "_change_data" );
25883269 val = getVal(elem);
25893270
25903271 // the current data will be also retrieved by beforeactivate
25913272 if ( e.type !== "focusout" || elem.type !== "radio" ) {
2592 - jQuery.data( elem, "_change_data", val );
 3273+ jQuery._data( elem, "_change_data", val );
25933274 }
2594 -
 3275+
25953276 if ( data === undefined || val === data ) {
25963277 return;
25973278 }
@@ -2598,33 +3279,33 @@
25993280 if ( data != null || val ) {
26003281 e.type = "change";
26013282 e.liveFired = undefined;
2602 - return jQuery.event.trigger( e, arguments[1], elem );
 3283+ jQuery.event.trigger( e, arguments[1], elem );
26033284 }
26043285 };
26053286
26063287 jQuery.event.special.change = {
26073288 filters: {
2608 - focusout: testChange,
 3289+ focusout: testChange,
26093290
26103291 beforedeactivate: testChange,
26113292
26123293 click: function( e ) {
2613 - var elem = e.target, type = elem.type;
 3294+ var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
26143295
2615 - if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
2616 - return testChange.call( this, e );
 3296+ if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) {
 3297+ testChange.call( this, e );
26173298 }
26183299 },
26193300
26203301 // Change has to be called before submit
26213302 // Keydown will be called before keypress, which is used in submit-event delegation
26223303 keydown: function( e ) {
2623 - var elem = e.target, type = elem.type;
 3304+ var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
26243305
2625 - if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
 3306+ if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) ||
26263307 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
26273308 type === "select-multiple" ) {
2628 - return testChange.call( this, e );
 3309+ testChange.call( this, e );
26293310 }
26303311 },
26313312
@@ -2633,7 +3314,7 @@
26343315 // information
26353316 beforeactivate: function( e ) {
26363317 var elem = e.target;
2637 - jQuery.data( elem, "_change_data", getVal(elem) );
 3318+ jQuery._data( elem, "_change_data", getVal(elem) );
26383319 }
26393320 },
26403321
@@ -2663,36 +3344,58 @@
26643345 }
26653346
26663347 function trigger( type, elem, args ) {
2667 - args[0].type = type;
2668 - return jQuery.event.handle.apply( elem, args );
 3348+ // Piggyback on a donor event to simulate a different one.
 3349+ // Fake originalEvent to avoid donor's stopPropagation, but if the
 3350+ // simulated event prevents default then we do the same on the donor.
 3351+ // Don't pass args or remember liveFired; they apply to the donor event.
 3352+ var event = jQuery.extend( {}, args[ 0 ] );
 3353+ event.type = type;
 3354+ event.originalEvent = {};
 3355+ event.liveFired = undefined;
 3356+ jQuery.event.handle.call( elem, event );
 3357+ if ( event.isDefaultPrevented() ) {
 3358+ args[ 0 ].preventDefault();
 3359+ }
26693360 }
26703361
26713362 // Create "bubbling" focus and blur events
2672 -if ( document.addEventListener ) {
 3363+if ( !jQuery.support.focusinBubbles ) {
26733364 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
 3365+
 3366+ // Attach a single capturing handler while someone wants focusin/focusout
 3367+ var attaches = 0;
 3368+
26743369 jQuery.event.special[ fix ] = {
26753370 setup: function() {
2676 - if ( focusCounts[fix]++ === 0 ) {
 3371+ if ( attaches++ === 0 ) {
26773372 document.addEventListener( orig, handler, true );
26783373 }
2679 - },
2680 - teardown: function() {
2681 - if ( --focusCounts[fix] === 0 ) {
 3374+ },
 3375+ teardown: function() {
 3376+ if ( --attaches === 0 ) {
26823377 document.removeEventListener( orig, handler, true );
26833378 }
26843379 }
26853380 };
26863381
2687 - function handler( e ) {
2688 - e = jQuery.event.fix( e );
 3382+ function handler( donor ) {
 3383+ // Donor event is always a native one; fix it and switch its type.
 3384+ // Let focusin/out handler cancel the donor focus/blur event.
 3385+ var e = jQuery.event.fix( donor );
26893386 e.type = fix;
2690 - return jQuery.event.trigger( e, null, e.target );
 3387+ e.originalEvent = {};
 3388+ jQuery.event.trigger( e, null, e.target );
 3389+ if ( e.isDefaultPrevented() ) {
 3390+ donor.preventDefault();
 3391+ }
26913392 }
26923393 });
26933394 }
26943395
26953396 jQuery.each(["bind", "one"], function( i, name ) {
26963397 jQuery.fn[ name ] = function( type, data, fn ) {
 3398+ var handler;
 3399+
26973400 // Handle object literals
26983401 if ( typeof type === "object" ) {
26993402 for ( var key in type ) {
@@ -2700,16 +3403,21 @@
27013404 }
27023405 return this;
27033406 }
2704 -
2705 - if ( jQuery.isFunction( data ) || data === false ) {
 3407+
 3408+ if ( arguments.length === 2 || data === false ) {
27063409 fn = data;
27073410 data = undefined;
27083411 }
27093412
2710 - var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
2711 - jQuery( this ).unbind( event, handler );
2712 - return fn.apply( this, arguments );
2713 - }) : fn;
 3413+ if ( name === "one" ) {
 3414+ handler = function( event ) {
 3415+ jQuery( this ).unbind( event, handler );
 3416+ return fn.apply( this, arguments );
 3417+ };
 3418+ handler.guid = fn.guid || jQuery.guid++;
 3419+ } else {
 3420+ handler = fn;
 3421+ }
27143422
27153423 if ( type === "unload" && name !== "one" ) {
27163424 this.one( type, data, fn );
@@ -2740,20 +3448,20 @@
27413449
27423450 return this;
27433451 },
2744 -
 3452+
27453453 delegate: function( selector, types, data, fn ) {
27463454 return this.live( types, data, fn, selector );
27473455 },
2748 -
 3456+
27493457 undelegate: function( selector, types, fn ) {
27503458 if ( arguments.length === 0 ) {
2751 - return this.unbind( "live" );
2752 -
 3459+ return this.unbind( "live" );
 3460+
27533461 } else {
27543462 return this.die( types, null, fn, selector );
27553463 }
27563464 },
2757 -
 3465+
27583466 trigger: function( type, data ) {
27593467 return this.each(function() {
27603468 jQuery.event.trigger( type, data, this );
@@ -2762,35 +3470,34 @@
27633471
27643472 triggerHandler: function( type, data ) {
27653473 if ( this[0] ) {
2766 - var event = jQuery.Event( type );
2767 - event.preventDefault();
2768 - event.stopPropagation();
2769 - jQuery.event.trigger( event, data, this[0] );
2770 - return event.result;
 3474+ return jQuery.event.trigger( type, data, this[0], true );
27713475 }
27723476 },
27733477
27743478 toggle: function( fn ) {
27753479 // Save reference to arguments for access in closure
27763480 var args = arguments,
2777 - i = 1;
 3481+ guid = fn.guid || jQuery.guid++,
 3482+ i = 0,
 3483+ toggler = function( event ) {
 3484+ // Figure out which function to execute
 3485+ var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
 3486+ jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
27783487
 3488+ // Make sure that clicks stop
 3489+ event.preventDefault();
 3490+
 3491+ // and execute the function
 3492+ return args[ lastToggle ].apply( this, arguments ) || false;
 3493+ };
 3494+
27793495 // link all the functions, so any of them can unbind this click handler
 3496+ toggler.guid = guid;
27803497 while ( i < args.length ) {
2781 - jQuery.proxy( fn, args[ i++ ] );
 3498+ args[ i++ ].guid = guid;
27823499 }
27833500
2784 - return this.click( jQuery.proxy( fn, function( event ) {
2785 - // Figure out which function to execute
2786 - var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
2787 - jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
2788 -
2789 - // Make sure that clicks stop
2790 - event.preventDefault();
2791 -
2792 - // and execute the function
2793 - return args[ lastToggle ].apply( this, arguments ) || false;
2794 - }));
 3501+ return this.click( toggler );
27953502 },
27963503
27973504 hover: function( fnOver, fnOut ) {
@@ -2810,17 +3517,25 @@
28113518 var type, i = 0, match, namespaces, preType,
28123519 selector = origSelector || this.selector,
28133520 context = origSelector ? this : jQuery( this.context );
2814 -
 3521+
28153522 if ( typeof types === "object" && !types.preventDefault ) {
28163523 for ( var key in types ) {
28173524 context[ name ]( key, data, types[key], selector );
28183525 }
2819 -
 3526+
28203527 return this;
28213528 }
28223529
2823 - if ( jQuery.isFunction( data ) ) {
2824 - fn = data;
 3530+ if ( name === "die" && !types &&
 3531+ origSelector && origSelector.charAt(0) === "." ) {
 3532+
 3533+ context.unbind( origSelector );
 3534+
 3535+ return this;
 3536+ }
 3537+
 3538+ if ( data === false || jQuery.isFunction( data ) ) {
 3539+ fn = data || returnFalse;
28253540 data = undefined;
28263541 }
28273542
@@ -2842,7 +3557,7 @@
28433558
28443559 preType = type;
28453560
2846 - if ( type === "focus" || type === "blur" ) {
 3561+ if ( liveMap[ type ] ) {
28473562 types.push( liveMap[ type ] + namespaces );
28483563 type = type + namespaces;
28493564
@@ -2862,7 +3577,7 @@
28633578 context.unbind( "live." + liveConvert( type, selector ), fn );
28643579 }
28653580 }
2866 -
 3581+
28673582 return this;
28683583 };
28693584 });
@@ -2871,17 +3586,13 @@
28723587 var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
28733588 elems = [],
28743589 selectors = [],
2875 - events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
 3590+ events = jQuery._data( this, "events" );
28763591
2877 - if ( typeof events === "function" ) {
2878 - events = events.events;
 3592+ // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
 3593+ if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
 3594+ return;
28793595 }
28803596
2881 - // Make sure we avoid non-left-click bubbling in Firefox (#3861)
2882 - if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
2883 - return;
2884 - }
2885 -
28863597 if ( event.namespace ) {
28873598 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
28883599 }
@@ -2909,7 +3620,7 @@
29103621 for ( j = 0; j < live.length; j++ ) {
29113622 handleObj = live[j];
29123623
2913 - if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
 3624+ if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {
29143625 elem = close.elem;
29153626 related = null;
29163627
@@ -2917,6 +3628,11 @@
29183629 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
29193630 event.type = handleObj.preType;
29203631 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
 3632+
 3633+ // Make sure not to accidentally match a child element with the same selector
 3634+ if ( related && jQuery.contains( elem, related ) ) {
 3635+ related = elem;
 3636+ }
29213637 }
29223638
29233639 if ( !related || related !== elem ) {
@@ -2955,7 +3671,7 @@
29563672 }
29573673
29583674 function liveConvert( type, selector ) {
2959 - return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
 3675+ return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&");
29603676 }
29613677
29623678 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
@@ -2979,27 +3695,11 @@
29803696 }
29813697 });
29823698
2983 -// Prevent memory leaks in IE
2984 -// Window isn't included so as not to unbind existing unload events
2985 -// More info:
2986 -// - http://isaacschlueter.com/2006/10/msie-memory-leaks/
2987 -if ( window.attachEvent && !window.addEventListener ) {
2988 - jQuery(window).bind("unload", function() {
2989 - for ( var id in jQuery.cache ) {
2990 - if ( jQuery.cache[ id ].handle ) {
2991 - // Try/Catch is to handle iframes being unloaded, see #4280
2992 - try {
2993 - jQuery.event.remove( jQuery.cache[ id ].handle.elem );
2994 - } catch(e) {}
2995 - }
2996 - }
2997 - });
2998 -}
29993699
30003700
30013701 /*!
3002 - * Sizzle CSS Selector Engine - v1.0
3003 - * Copyright 2009, The Dojo Foundation
 3702+ * Sizzle CSS Selector Engine
 3703+ * Copyright 2011, The Dojo Foundation
30043704 * Released under the MIT, BSD, and GPL Licenses.
30053705 * More information: http://sizzlejs.com/
30063706 */
@@ -3009,7 +3709,9 @@
30103710 done = 0,
30113711 toString = Object.prototype.toString,
30123712 hasDuplicate = false,
3013 - baseHasDuplicate = true;
 3713+ baseHasDuplicate = true,
 3714+ rBackslash = /\\/g,
 3715+ rNonWord = /\W/;
30143716
30153717 // Here we check if the JavaScript engine is using some sort of
30163718 // optimization where it does not always call our comparision
@@ -3208,7 +3910,7 @@
32093911 match.splice( 1, 1 );
32103912
32113913 if ( left.substr( left.length - 1 ) !== "\\" ) {
3212 - match[1] = (match[1] || "").replace(/\\/g, "");
 3914+ match[1] = (match[1] || "").replace( rBackslash, "" );
32133915 set = Expr.find[ type ]( match, context, isXML );
32143916
32153917 if ( set != null ) {
@@ -3220,7 +3922,9 @@
32213923 }
32223924
32233925 if ( !set ) {
3224 - set = context.getElementsByTagName( "*" );
 3926+ set = typeof context.getElementsByTagName !== "undefined" ?
 3927+ context.getElementsByTagName( "*" ) :
 3928+ [];
32253929 }
32263930
32273931 return { set: set, expr: expr };
@@ -3328,9 +4032,9 @@
33294033 ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
33304034 CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
33314035 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
3332 - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
 4036+ ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
33334037 TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
3334 - CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
 4038+ CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
33354039 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
33364040 PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
33374041 },
@@ -3345,13 +4049,16 @@
33464050 attrHandle: {
33474051 href: function( elem ) {
33484052 return elem.getAttribute( "href" );
 4053+ },
 4054+ type: function( elem ) {
 4055+ return elem.getAttribute( "type" );
33494056 }
33504057 },
33514058
33524059 relative: {
33534060 "+": function(checkSet, part){
33544061 var isPartStr = typeof part === "string",
3355 - isTag = isPartStr && !/\W/.test( part ),
 4062+ isTag = isPartStr && !rNonWord.test( part ),
33564063 isPartStrNotTag = isPartStr && !isTag;
33574064
33584065 if ( isTag ) {
@@ -3379,7 +4086,7 @@
33804087 i = 0,
33814088 l = checkSet.length;
33824089
3383 - if ( isPartStr && !/\W/.test( part ) ) {
 4090+ if ( isPartStr && !rNonWord.test( part ) ) {
33844091 part = part.toLowerCase();
33854092
33864093 for ( ; i < l; i++ ) {
@@ -3413,7 +4120,7 @@
34144121 doneName = done++,
34154122 checkFn = dirCheck;
34164123
3417 - if ( typeof part === "string" && !/\W/.test(part) ) {
 4124+ if ( typeof part === "string" && !rNonWord.test( part ) ) {
34184125 part = part.toLowerCase();
34194126 nodeCheck = part;
34204127 checkFn = dirNodeCheck;
@@ -3427,7 +4134,7 @@
34284135 doneName = done++,
34294136 checkFn = dirCheck;
34304137
3431 - if ( typeof part === "string" && !/\W/.test( part ) ) {
 4138+ if ( typeof part === "string" && !rNonWord.test( part ) ) {
34324139 part = part.toLowerCase();
34334140 nodeCheck = part;
34344141 checkFn = dirNodeCheck;
@@ -3463,12 +4170,14 @@
34644171 },
34654172
34664173 TAG: function( match, context ) {
3467 - return context.getElementsByTagName( match[1] );
 4174+ if ( typeof context.getElementsByTagName !== "undefined" ) {
 4175+ return context.getElementsByTagName( match[1] );
 4176+ }
34684177 }
34694178 },
34704179 preFilter: {
34714180 CLASS: function( match, curLoop, inplace, result, not, isXML ) {
3472 - match = " " + match[1].replace(/\\/g, "") + " ";
 4181+ match = " " + match[1].replace( rBackslash, "" ) + " ";
34734182
34744183 if ( isXML ) {
34754184 return match;
@@ -3476,7 +4185,7 @@
34774186
34784187 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
34794188 if ( elem ) {
3480 - if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
 4189+ if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
34814190 if ( !inplace ) {
34824191 result.push( elem );
34834192 }
@@ -3491,17 +4200,23 @@
34924201 },
34934202
34944203 ID: function( match ) {
3495 - return match[1].replace(/\\/g, "");
 4204+ return match[1].replace( rBackslash, "" );
34964205 },
34974206
34984207 TAG: function( match, curLoop ) {
3499 - return match[1].toLowerCase();
 4208+ return match[1].replace( rBackslash, "" ).toLowerCase();
35004209 },
35014210
35024211 CHILD: function( match ) {
35034212 if ( match[1] === "nth" ) {
 4213+ if ( !match[2] ) {
 4214+ Sizzle.error( match[0] );
 4215+ }
 4216+
 4217+ match[2] = match[2].replace(/^\+|\s*/g, '');
 4218+
35044219 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
3505 - var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
 4220+ var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
35064221 match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
35074222 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
35084223
@@ -3509,6 +4224,9 @@
35104225 match[2] = (test[1] + (test[2] || 1)) - 0;
35114226 match[3] = test[3] - 0;
35124227 }
 4228+ else if ( match[2] ) {
 4229+ Sizzle.error( match[0] );
 4230+ }
35134231
35144232 // TODO: Move to normal caching system
35154233 match[0] = done++;
@@ -3517,12 +4235,15 @@
35184236 },
35194237
35204238 ATTR: function( match, curLoop, inplace, result, not, isXML ) {
3521 - var name = match[1].replace(/\\/g, "");
 4239+ var name = match[1] = match[1].replace( rBackslash, "" );
35224240
35234241 if ( !isXML && Expr.attrMap[name] ) {
35244242 match[1] = Expr.attrMap[name];
35254243 }
35264244
 4245+ // Handle if an un-quoted value was used
 4246+ match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
 4247+
35274248 if ( match[2] === "~=" ) {
35284249 match[4] = " " + match[4] + " ";
35294250 }
@@ -3576,7 +4297,9 @@
35774298 selected: function( elem ) {
35784299 // Accessing this property makes selected-by-default
35794300 // options in Safari work properly
3580 - elem.parentNode.selectedIndex;
 4301+ if ( elem.parentNode ) {
 4302+ elem.parentNode.selectedIndex;
 4303+ }
35814304
35824305 return elem.selected === true;
35834306 },
@@ -3598,41 +4321,53 @@
35994322 },
36004323
36014324 text: function( elem ) {
3602 - return "text" === elem.type;
 4325+ var attr = elem.getAttribute( "type" ), type = elem.type;
 4326+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
 4327+ // use getAttribute instead to test this case
 4328+ return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
36034329 },
 4330+
36044331 radio: function( elem ) {
3605 - return "radio" === elem.type;
 4332+ return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
36064333 },
36074334
36084335 checkbox: function( elem ) {
3609 - return "checkbox" === elem.type;
 4336+ return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
36104337 },
36114338
36124339 file: function( elem ) {
3613 - return "file" === elem.type;
 4340+ return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
36144341 },
 4342+
36154343 password: function( elem ) {
3616 - return "password" === elem.type;
 4344+ return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
36174345 },
36184346
36194347 submit: function( elem ) {
3620 - return "submit" === elem.type;
 4348+ var name = elem.nodeName.toLowerCase();
 4349+ return (name === "input" || name === "button") && "submit" === elem.type;
36214350 },
36224351
36234352 image: function( elem ) {
3624 - return "image" === elem.type;
 4353+ return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
36254354 },
36264355
36274356 reset: function( elem ) {
3628 - return "reset" === elem.type;
 4357+ var name = elem.nodeName.toLowerCase();
 4358+ return (name === "input" || name === "button") && "reset" === elem.type;
36294359 },
36304360
36314361 button: function( elem ) {
3632 - return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
 4362+ var name = elem.nodeName.toLowerCase();
 4363+ return name === "input" && "button" === elem.type || name === "button";
36334364 },
36344365
36354366 input: function( elem ) {
36364367 return (/input|select|textarea|button/i).test( elem.nodeName );
 4368+ },
 4369+
 4370+ focus: function( elem ) {
 4371+ return elem === elem.ownerDocument.activeElement;
36374372 }
36384373 },
36394374 setFilters: {
@@ -3691,7 +4426,7 @@
36924427 return true;
36934428
36944429 } else {
3695 - Sizzle.error( "Syntax error, unrecognized expression: " + name );
 4430+ Sizzle.error( name );
36964431 }
36974432 },
36984433
@@ -3885,6 +4620,16 @@
38864621
38874622 } else {
38884623 sortOrder = function( a, b ) {
 4624+ // The nodes are identical, we can exit early
 4625+ if ( a === b ) {
 4626+ hasDuplicate = true;
 4627+ return 0;
 4628+
 4629+ // Fallback to using sourceIndex (in IE) if it's available on both nodes
 4630+ } else if ( a.sourceIndex && b.sourceIndex ) {
 4631+ return a.sourceIndex - b.sourceIndex;
 4632+ }
 4633+
38894634 var al, bl,
38904635 ap = [],
38914636 bp = [],
@@ -3892,13 +4637,8 @@
38934638 bup = b.parentNode,
38944639 cur = aup;
38954640
3896 - // The nodes are identical, we can exit early
3897 - if ( a === b ) {
3898 - hasDuplicate = true;
3899 - return 0;
3900 -
39014641 // If the nodes are siblings (or identical) we can do a quick check
3902 - } else if ( aup === bup ) {
 4642+ if ( aup === bup ) {
39034643 return siblingCheck( a, b );
39044644
39054645 // If no parents were found then the nodes are disconnected
@@ -4081,13 +4821,47 @@
40824822 Sizzle = function( query, context, extra, seed ) {
40834823 context = context || document;
40844824
4085 - // Make sure that attribute selectors are quoted
4086 - query = query.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
4087 -
40884825 // Only use querySelectorAll on non-XML documents
40894826 // (ID selectors don't work in non-HTML documents)
40904827 if ( !seed && !Sizzle.isXML(context) ) {
 4828+ // See if we find a selector to speed up
 4829+ var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
 4830+
 4831+ if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
 4832+ // Speed-up: Sizzle("TAG")
 4833+ if ( match[1] ) {
 4834+ return makeArray( context.getElementsByTagName( query ), extra );
 4835+
 4836+ // Speed-up: Sizzle(".CLASS")
 4837+ } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
 4838+ return makeArray( context.getElementsByClassName( match[2] ), extra );
 4839+ }
 4840+ }
 4841+
40914842 if ( context.nodeType === 9 ) {
 4843+ // Speed-up: Sizzle("body")
 4844+ // The body element only exists once, optimize finding it
 4845+ if ( query === "body" && context.body ) {
 4846+ return makeArray( [ context.body ], extra );
 4847+
 4848+ // Speed-up: Sizzle("#ID")
 4849+ } else if ( match && match[3] ) {
 4850+ var elem = context.getElementById( match[3] );
 4851+
 4852+ // Check parentNode to catch when Blackberry 4.6 returns
 4853+ // nodes that are no longer in the document #6963
 4854+ if ( elem && elem.parentNode ) {
 4855+ // Handle the case where IE and Opera return items
 4856+ // by name instead of ID
 4857+ if ( elem.id === match[3] ) {
 4858+ return makeArray( [ elem ], extra );
 4859+ }
 4860+
 4861+ } else {
 4862+ return makeArray( [], extra );
 4863+ }
 4864+ }
 4865+
40924866 try {
40934867 return makeArray( context.querySelectorAll(query), extra );
40944868 } catch(qsaError) {}
@@ -4097,20 +4871,30 @@
40984872 // and working up from there (Thanks to Andrew Dupont for the technique)
40994873 // IE 8 doesn't work on object elements
41004874 } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
4101 - var old = context.getAttribute( "id" ),
4102 - nid = old || id;
 4875+ var oldContext = context,
 4876+ old = context.getAttribute( "id" ),
 4877+ nid = old || id,
 4878+ hasParent = context.parentNode,
 4879+ relativeHierarchySelector = /^\s*[+~]/.test( query );
41034880
41044881 if ( !old ) {
41054882 context.setAttribute( "id", nid );
 4883+ } else {
 4884+ nid = nid.replace( /'/g, "\\$&" );
41064885 }
 4886+ if ( relativeHierarchySelector && hasParent ) {
 4887+ context = context.parentNode;
 4888+ }
41074889
41084890 try {
4109 - return makeArray( context.querySelectorAll( "#" + nid + " " + query ), extra );
 4891+ if ( !relativeHierarchySelector || hasParent ) {
 4892+ return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
 4893+ }
41104894
41114895 } catch(pseudoError) {
41124896 } finally {
41134897 if ( !old ) {
4114 - context.removeAttribute( "id" );
 4898+ oldContext.removeAttribute( "id" );
41154899 }
41164900 }
41174901 }
@@ -4130,19 +4914,23 @@
41314915
41324916 (function(){
41334917 var html = document.documentElement,
4134 - matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector,
4135 - pseudoWorks = false;
 4918+ matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
41364919
4137 - try {
4138 - // This should fail with an exception
4139 - // Gecko does not error, returns false instead
4140 - matches.call( document.documentElement, "[test!='']:sizzle" );
 4920+ if ( matches ) {
 4921+ // Check to see if it's possible to do matchesSelector
 4922+ // on a disconnected node (IE 9 fails this)
 4923+ var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
 4924+ pseudoWorks = false;
 4925+
 4926+ try {
 4927+ // This should fail with an exception
 4928+ // Gecko does not error, returns false instead
 4929+ matches.call( document.documentElement, "[test!='']:sizzle" );
41414930
4142 - } catch( pseudoError ) {
4143 - pseudoWorks = true;
4144 - }
 4931+ } catch( pseudoError ) {
 4932+ pseudoWorks = true;
 4933+ }
41454934
4146 - if ( matches ) {
41474935 Sizzle.matchesSelector = function( node, expr ) {
41484936 // Make sure that attribute selectors are quoted
41494937 expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
@@ -4150,7 +4938,15 @@
41514939 if ( !Sizzle.isXML( node ) ) {
41524940 try {
41534941 if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
4154 - return matches.call( node, expr );
 4942+ var ret = matches.call( node, expr );
 4943+
 4944+ // IE 9's matchesSelector returns false on disconnected nodes
 4945+ if ( ret || !disconnectedMatch ||
 4946+ // As well, disconnected nodes are said to be in a document
 4947+ // fragment in IE 9, so check for that
 4948+ node.document && node.document.nodeType !== 11 ) {
 4949+ return ret;
 4950+ }
41554951 }
41564952 } catch(e) {}
41574953 }
@@ -4328,21 +5124,41 @@
43295125 rmultiselector = /,/,
43305126 isSimple = /^.[^:#\[\.,]*$/,
43315127 slice = Array.prototype.slice,
4332 - POS = jQuery.expr.match.POS;
 5128+ POS = jQuery.expr.match.POS,
 5129+ // methods guaranteed to produce a unique set when starting from a unique set
 5130+ guaranteedUnique = {
 5131+ children: true,
 5132+ contents: true,
 5133+ next: true,
 5134+ prev: true
 5135+ };
43335136
43345137 jQuery.fn.extend({
43355138 find: function( selector ) {
 5139+ var self = this,
 5140+ i, l;
 5141+
 5142+ if ( typeof selector !== "string" ) {
 5143+ return jQuery( selector ).filter(function() {
 5144+ for ( i = 0, l = self.length; i < l; i++ ) {
 5145+ if ( jQuery.contains( self[ i ], this ) ) {
 5146+ return true;
 5147+ }
 5148+ }
 5149+ });
 5150+ }
 5151+
43365152 var ret = this.pushStack( "", "find", selector ),
4337 - length = 0;
 5153+ length, n, r;
43385154
4339 - for ( var i = 0, l = this.length; i < l; i++ ) {
 5155+ for ( i = 0, l = this.length; i < l; i++ ) {
43405156 length = ret.length;
43415157 jQuery.find( selector, this[i], ret );
43425158
43435159 if ( i > 0 ) {
43445160 // Make sure that the results are unique
4345 - for ( var n = length; n < ret.length; n++ ) {
4346 - for ( var r = 0; r < length; r++ ) {
 5161+ for ( n = length; n < ret.length; n++ ) {
 5162+ for ( r = 0; r < length; r++ ) {
43475163 if ( ret[r] === ret[n] ) {
43485164 ret.splice(n--, 1);
43495165 break;
@@ -4373,14 +5189,17 @@
43745190 filter: function( selector ) {
43755191 return this.pushStack( winnow(this, selector, true), "filter", selector );
43765192 },
4377 -
 5193+
43785194 is: function( selector ) {
4379 - return !!selector && jQuery.filter( selector, this ).length > 0;
 5195+ return !!selector && ( typeof selector === "string" ?
 5196+ jQuery.filter( selector, this ).length > 0 :
 5197+ this.filter( selector ).length > 0 );
43805198 },
43815199
43825200 closest: function( selectors, context ) {
43835201 var ret = [], i, l, cur = this[0];
4384 -
 5202+
 5203+ // Array
43855204 if ( jQuery.isArray( selectors ) ) {
43865205 var match, selector,
43875206 matches = {},
@@ -4390,8 +5209,8 @@
43915210 for ( i = 0, l = selectors.length; i < l; i++ ) {
43925211 selector = selectors[i];
43935212
4394 - if ( !matches[selector] ) {
4395 - matches[selector] = jQuery.expr.match.POS.test( selector ) ?
 5213+ if ( !matches[ selector ] ) {
 5214+ matches[ selector ] = POS.test( selector ) ?
43965215 jQuery( selector, context || this.context ) :
43975216 selector;
43985217 }
@@ -4399,9 +5218,9 @@
44005219
44015220 while ( cur && cur.ownerDocument && cur !== context ) {
44025221 for ( selector in matches ) {
4403 - match = matches[selector];
 5222+ match = matches[ selector ];
44045223
4405 - if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
 5224+ if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) {
44065225 ret.push({ selector: selector, elem: cur, level: level });
44075226 }
44085227 }
@@ -4414,8 +5233,10 @@
44155234 return ret;
44165235 }
44175236
4418 - var pos = POS.test( selectors ) ?
4419 - jQuery( selectors, context || this.context ) : null;
 5237+ // String
 5238+ var pos = POS.test( selectors ) || typeof selectors !== "string" ?
 5239+ jQuery( selectors, context || this.context ) :
 5240+ 0;
44205241
44215242 for ( i = 0, l = this.length; i < l; i++ ) {
44225243 cur = this[i];
@@ -4427,18 +5248,18 @@
44285249
44295250 } else {
44305251 cur = cur.parentNode;
4431 - if ( !cur || !cur.ownerDocument || cur === context ) {
 5252+ if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
44325253 break;
44335254 }
44345255 }
44355256 }
44365257 }
44375258
4438 - ret = ret.length > 1 ? jQuery.unique(ret) : ret;
4439 -
 5259+ ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
 5260+
44405261 return this.pushStack( ret, "closest", selectors );
44415262 },
4442 -
 5263+
44435264 // Determine the position of an element within
44445265 // the matched set of elements
44455266 index: function( elem ) {
@@ -4456,8 +5277,8 @@
44575278
44585279 add: function( selector, context ) {
44595280 var set = typeof selector === "string" ?
4460 - jQuery( selector, context || this.context ) :
4461 - jQuery.makeArray( selector ),
 5281+ jQuery( selector, context ) :
 5282+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
44625283 all = jQuery.merge( this.get(), set );
44635284
44645285 return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
@@ -4518,8 +5339,13 @@
45195340 }
45205341 }, function( name, fn ) {
45215342 jQuery.fn[ name ] = function( until, selector ) {
4522 - var ret = jQuery.map( this, fn, until );
4523 -
 5343+ var ret = jQuery.map( this, fn, until ),
 5344+ // The variable 'args' was introduced in
 5345+ // https://github.com/jquery/jquery/commit/52a0238
 5346+ // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.
 5347+ // http://code.google.com/p/v8/issues/detail?id=1050
 5348+ args = slice.call(arguments);
 5349+
45245350 if ( !runtil.test( name ) ) {
45255351 selector = until;
45265352 }
@@ -4528,13 +5354,13 @@
45295355 ret = jQuery.filter( selector, ret );
45305356 }
45315357
4532 - ret = this.length > 1 ? jQuery.unique( ret ) : ret;
 5358+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
45335359
45345360 if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
45355361 ret = ret.reverse();
45365362 }
45375363
4538 - return this.pushStack( ret, name, slice.call(arguments).join(",") );
 5364+ return this.pushStack( ret, name, args.join(",") );
45395365 };
45405366 });
45415367
@@ -4548,7 +5374,7 @@
45495375 jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
45505376 jQuery.find.matches(expr, elems);
45515377 },
4552 -
 5378+
45535379 dir: function( elem, dir, until ) {
45545380 var matched = [],
45555381 cur = elem[ dir ];
@@ -4590,6 +5416,11 @@
45915417
45925418 // Implement the identical functionality for filter and not
45935419 function winnow( elements, qualifier, keep ) {
 5420+
 5421+ // Can't pass null or undefined to indexOf in Firefox 4
 5422+ // Set to 0 to skip string check
 5423+ qualifier = qualifier || 0;
 5424+
45945425 if ( jQuery.isFunction( qualifier ) ) {
45955426 return jQuery.grep(elements, function( elem, i ) {
45965427 var retVal = !!qualifier.call( elem, i, elem );
@@ -4628,9 +5459,10 @@
46295460 rtbody = /<tbody/i,
46305461 rhtml = /<|&#?\w+;/,
46315462 rnocache = /<(?:script|object|embed|option|style)/i,
4632 - // checked="checked" or checked (html5)
 5463+ // checked="checked" or checked
46335464 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
4634 - raction = /\=([^="'>\s]+\/)>/g,
 5465+ rscriptType = /\/(java|ecma)script/i,
 5466+ rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
46355467 wrapMap = {
46365468 option: [ 1, "<select multiple='multiple'>", "</select>" ],
46375469 legend: [ 1, "<fieldset>", "</fieldset>" ],
@@ -4691,7 +5523,7 @@
46925524 }
46935525
46945526 return elem;
4695 - }).append(this);
 5527+ }).append( this );
46965528 }
46975529
46985530 return this;
@@ -4770,7 +5602,7 @@
47715603 return set;
47725604 }
47735605 },
4774 -
 5606+
47755607 // keepData is for internal use only--do not document
47765608 remove: function( selector, keepData ) {
47775609 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
@@ -4781,11 +5613,11 @@
47825614 }
47835615
47845616 if ( elem.parentNode ) {
4785 - elem.parentNode.removeChild( elem );
 5617+ elem.parentNode.removeChild( elem );
47865618 }
47875619 }
47885620 }
4789 -
 5621+
47905622 return this;
47915623 },
47925624
@@ -4801,48 +5633,17 @@
48025634 elem.removeChild( elem.firstChild );
48035635 }
48045636 }
4805 -
 5637+
48065638 return this;
48075639 },
48085640
4809 - clone: function( events ) {
4810 - // Do the clone
4811 - var ret = this.map(function() {
4812 - if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
4813 - // IE copies events bound via attachEvent when
4814 - // using cloneNode. Calling detachEvent on the
4815 - // clone will also remove the events from the orignal
4816 - // In order to get around this, we use innerHTML.
4817 - // Unfortunately, this means some modifications to
4818 - // attributes in IE that are actually only stored
4819 - // as properties will not be copied (such as the
4820 - // the name attribute on an input).
4821 - var html = this.outerHTML,
4822 - ownerDocument = this.ownerDocument;
 5641+ clone: function( dataAndEvents, deepDataAndEvents ) {
 5642+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
 5643+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
48235644
4824 - if ( !html ) {
4825 - var div = ownerDocument.createElement("div");
4826 - div.appendChild( this.cloneNode(true) );
4827 - html = div.innerHTML;
4828 - }
4829 -
4830 - return jQuery.clean([html.replace(rinlinejQuery, "")
4831 - // Handle the case in IE 8 where action=/test/> self-closes a tag
4832 - .replace(raction, '="$1">')
4833 - .replace(rleadingWhitespace, "")], ownerDocument)[0];
4834 - } else {
4835 - return this.cloneNode(true);
4836 - }
 5645+ return this.map( function () {
 5646+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
48375647 });
4838 -
4839 - // Copy the events from the original to the clone
4840 - if ( events === true ) {
4841 - cloneCopyEvent( this, ret );
4842 - cloneCopyEvent( this.find("*"), ret.find("*") );
4843 - }
4844 -
4845 - // Return the cloned set
4846 - return ret;
48475648 },
48485649
48495650 html: function( value ) {
@@ -4914,7 +5715,9 @@
49155716 }
49165717 });
49175718 } else {
4918 - return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
 5719+ return this.length ?
 5720+ this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
 5721+ this;
49195722 }
49205723 },
49215724
@@ -4952,9 +5755,9 @@
49535756 } else {
49545757 results = jQuery.buildFragment( args, this, scripts );
49555758 }
4956 -
 5759+
49575760 fragment = results.fragment;
4958 -
 5761+
49595762 if ( fragment.childNodes.length === 1 ) {
49605763 first = fragment = fragment.firstChild;
49615764 } else {
@@ -4964,13 +5767,20 @@
49655768 if ( first ) {
49665769 table = table && jQuery.nodeName( first, "tr" );
49675770
4968 - for ( var i = 0, l = this.length; i < l; i++ ) {
 5771+ for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
49695772 callback.call(
49705773 table ?
49715774 root(this[i], first) :
49725775 this[i],
4973 - i > 0 || results.cacheable || this.length > 1 ?
4974 - fragment.cloneNode(true) :
 5776+ // Make sure that we do not leak memory by inadvertently discarding
 5777+ // the original fragment (which might have attached data) instead of
 5778+ // using it; in addition, use the original fragment object for the last
 5779+ // item instead of first because it can end up being emptied incorrectly
 5780+ // in certain situations (Bug #8070).
 5781+ // Fragments from the fragment cache must always be cloned and never used
 5782+ // in place.
 5783+ results.cacheable || (l > 1 && i < lastIndex) ?
 5784+ jQuery.clone( fragment, true, true ) :
49755785 fragment
49765786 );
49775787 }
@@ -4992,48 +5802,109 @@
49935803 elem;
49945804 }
49955805
4996 -function cloneCopyEvent(orig, ret) {
4997 - var i = 0;
 5806+function cloneCopyEvent( src, dest ) {
49985807
4999 - ret.each(function() {
5000 - if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
5001 - return;
5002 - }
 5808+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
 5809+ return;
 5810+ }
50035811
5004 - var oldData = jQuery.data( orig[i++] ),
5005 - curData = jQuery.data( this, oldData ),
5006 - events = oldData && oldData.events;
 5812+ var internalKey = jQuery.expando,
 5813+ oldData = jQuery.data( src ),
 5814+ curData = jQuery.data( dest, oldData );
50075815
 5816+ // Switch to use the internal data object, if it exists, for the next
 5817+ // stage of data copying
 5818+ if ( (oldData = oldData[ internalKey ]) ) {
 5819+ var events = oldData.events;
 5820+ curData = curData[ internalKey ] = jQuery.extend({}, oldData);
 5821+
50085822 if ( events ) {
50095823 delete curData.handle;
50105824 curData.events = {};
50115825
50125826 for ( var type in events ) {
5013 - for ( var handler in events[ type ] ) {
5014 - jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
 5827+ for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
 5828+ jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
50155829 }
50165830 }
50175831 }
5018 - });
 5832+ }
50195833 }
50205834
 5835+function cloneFixAttributes( src, dest ) {
 5836+ var nodeName;
 5837+
 5838+ // We do not need to do anything for non-Elements
 5839+ if ( dest.nodeType !== 1 ) {
 5840+ return;
 5841+ }
 5842+
 5843+ // clearAttributes removes the attributes, which we don't want,
 5844+ // but also removes the attachEvent events, which we *do* want
 5845+ if ( dest.clearAttributes ) {
 5846+ dest.clearAttributes();
 5847+ }
 5848+
 5849+ // mergeAttributes, in contrast, only merges back on the
 5850+ // original attributes, not the events
 5851+ if ( dest.mergeAttributes ) {
 5852+ dest.mergeAttributes( src );
 5853+ }
 5854+
 5855+ nodeName = dest.nodeName.toLowerCase();
 5856+
 5857+ // IE6-8 fail to clone children inside object elements that use
 5858+ // the proprietary classid attribute value (rather than the type
 5859+ // attribute) to identify the type of content to display
 5860+ if ( nodeName === "object" ) {
 5861+ dest.outerHTML = src.outerHTML;
 5862+
 5863+ } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
 5864+ // IE6-8 fails to persist the checked state of a cloned checkbox
 5865+ // or radio button. Worse, IE6-7 fail to give the cloned element
 5866+ // a checked appearance if the defaultChecked value isn't also set
 5867+ if ( src.checked ) {
 5868+ dest.defaultChecked = dest.checked = src.checked;
 5869+ }
 5870+
 5871+ // IE6-7 get confused and end up setting the value of a cloned
 5872+ // checkbox/radio button to an empty string instead of "on"
 5873+ if ( dest.value !== src.value ) {
 5874+ dest.value = src.value;
 5875+ }
 5876+
 5877+ // IE6-8 fails to return the selected option to the default selected
 5878+ // state when cloning options
 5879+ } else if ( nodeName === "option" ) {
 5880+ dest.selected = src.defaultSelected;
 5881+
 5882+ // IE6-8 fails to set the defaultValue to the correct value when
 5883+ // cloning other types of input fields
 5884+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
 5885+ dest.defaultValue = src.defaultValue;
 5886+ }
 5887+
 5888+ // Event data gets referenced instead of copied if the expando
 5889+ // gets copied too
 5890+ dest.removeAttribute( jQuery.expando );
 5891+}
 5892+
50215893 jQuery.buildFragment = function( args, nodes, scripts ) {
50225894 var fragment, cacheable, cacheresults,
50235895 doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
50245896
5025 - // Only cache "small" (1/2 KB) strings that are associated with the main document
 5897+ // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
50265898 // Cloning options loses the selected state, so don't cache them
50275899 // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
50285900 // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
50295901 if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
5030 - !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
 5902+ args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
50315903
50325904 cacheable = true;
 5905+
50335906 cacheresults = jQuery.fragments[ args[0] ];
5034 - if ( cacheresults ) {
5035 - if ( cacheresults !== 1 ) {
5036 - fragment = cacheresults;
5037 - }
 5907+ if ( cacheresults && cacheresults !== 1 ) {
 5908+ fragment = cacheresults;
50385909 }
50395910 }
50405911
@@ -5062,25 +5933,101 @@
50635934 var ret = [],
50645935 insert = jQuery( selector ),
50655936 parent = this.length === 1 && this[0].parentNode;
5066 -
 5937+
50675938 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
50685939 insert[ original ]( this[0] );
50695940 return this;
5070 -
 5941+
50715942 } else {
50725943 for ( var i = 0, l = insert.length; i < l; i++ ) {
50735944 var elems = (i > 0 ? this.clone(true) : this).get();
50745945 jQuery( insert[i] )[ original ]( elems );
50755946 ret = ret.concat( elems );
50765947 }
5077 -
 5948+
50785949 return this.pushStack( ret, name, insert.selector );
50795950 }
50805951 };
50815952 });
50825953
 5954+function getAll( elem ) {
 5955+ if ( "getElementsByTagName" in elem ) {
 5956+ return elem.getElementsByTagName( "*" );
 5957+
 5958+ } else if ( "querySelectorAll" in elem ) {
 5959+ return elem.querySelectorAll( "*" );
 5960+
 5961+ } else {
 5962+ return [];
 5963+ }
 5964+}
 5965+
 5966+// Used in clean, fixes the defaultChecked property
 5967+function fixDefaultChecked( elem ) {
 5968+ if ( elem.type === "checkbox" || elem.type === "radio" ) {
 5969+ elem.defaultChecked = elem.checked;
 5970+ }
 5971+}
 5972+// Finds all inputs and passes them to fixDefaultChecked
 5973+function findInputs( elem ) {
 5974+ if ( jQuery.nodeName( elem, "input" ) ) {
 5975+ fixDefaultChecked( elem );
 5976+ } else if ( elem.getElementsByTagName ) {
 5977+ jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
 5978+ }
 5979+}
 5980+
50835981 jQuery.extend({
 5982+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
 5983+ var clone = elem.cloneNode(true),
 5984+ srcElements,
 5985+ destElements,
 5986+ i;
 5987+
 5988+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
 5989+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
 5990+ // IE copies events bound via attachEvent when using cloneNode.
 5991+ // Calling detachEvent on the clone will also remove the events
 5992+ // from the original. In order to get around this, we use some
 5993+ // proprietary methods to clear the events. Thanks to MooTools
 5994+ // guys for this hotness.
 5995+
 5996+ cloneFixAttributes( elem, clone );
 5997+
 5998+ // Using Sizzle here is crazy slow, so we use getElementsByTagName
 5999+ // instead
 6000+ srcElements = getAll( elem );
 6001+ destElements = getAll( clone );
 6002+
 6003+ // Weird iteration because IE will replace the length property
 6004+ // with an element if you are cloning the body and one of the
 6005+ // elements on the page has a name or id of "length"
 6006+ for ( i = 0; srcElements[i]; ++i ) {
 6007+ cloneFixAttributes( srcElements[i], destElements[i] );
 6008+ }
 6009+ }
 6010+
 6011+ // Copy the events from the original to the clone
 6012+ if ( dataAndEvents ) {
 6013+ cloneCopyEvent( elem, clone );
 6014+
 6015+ if ( deepDataAndEvents ) {
 6016+ srcElements = getAll( elem );
 6017+ destElements = getAll( clone );
 6018+
 6019+ for ( i = 0; srcElements[i]; ++i ) {
 6020+ cloneCopyEvent( srcElements[i], destElements[i] );
 6021+ }
 6022+ }
 6023+ }
 6024+
 6025+ // Return the cloned set
 6026+ return clone;
 6027+ },
 6028+
50846029 clean: function( elems, context, fragment, scripts ) {
 6030+ var checkScriptType;
 6031+
50856032 context = context || document;
50866033
50876034 // !context.createElement fails in IE with an error but returns typeof 'object'
@@ -5088,7 +6035,7 @@
50896036 context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
50906037 }
50916038
5092 - var ret = [];
 6039+ var ret = [], j;
50936040
50946041 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
50956042 if ( typeof elem === "number" ) {
@@ -5100,54 +6047,67 @@
51016048 }
51026049
51036050 // Convert html string into DOM nodes
5104 - if ( typeof elem === "string" && !rhtml.test( elem ) ) {
5105 - elem = context.createTextNode( elem );
 6051+ if ( typeof elem === "string" ) {
 6052+ if ( !rhtml.test( elem ) ) {
 6053+ elem = context.createTextNode( elem );
 6054+ } else {
 6055+ // Fix "XHTML"-style tags in all browsers
 6056+ elem = elem.replace(rxhtmlTag, "<$1></$2>");
51066057
5107 - } else if ( typeof elem === "string" ) {
5108 - // Fix "XHTML"-style tags in all browsers
5109 - elem = elem.replace(rxhtmlTag, "<$1></$2>");
 6058+ // Trim whitespace, otherwise indexOf won't work as expected
 6059+ var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
 6060+ wrap = wrapMap[ tag ] || wrapMap._default,
 6061+ depth = wrap[0],
 6062+ div = context.createElement("div");
51106063
5111 - // Trim whitespace, otherwise indexOf won't work as expected
5112 - var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
5113 - wrap = wrapMap[ tag ] || wrapMap._default,
5114 - depth = wrap[0],
5115 - div = context.createElement("div");
 6064+ // Go to html and back, then peel off extra wrappers
 6065+ div.innerHTML = wrap[1] + elem + wrap[2];
51166066
5117 - // Go to html and back, then peel off extra wrappers
5118 - div.innerHTML = wrap[1] + elem + wrap[2];
 6067+ // Move to the right depth
 6068+ while ( depth-- ) {
 6069+ div = div.lastChild;
 6070+ }
51196071
5120 - // Move to the right depth
5121 - while ( depth-- ) {
5122 - div = div.lastChild;
5123 - }
 6072+ // Remove IE's autoinserted <tbody> from table fragments
 6073+ if ( !jQuery.support.tbody ) {
51246074
5125 - // Remove IE's autoinserted <tbody> from table fragments
5126 - if ( !jQuery.support.tbody ) {
 6075+ // String was a <table>, *may* have spurious <tbody>
 6076+ var hasBody = rtbody.test(elem),
 6077+ tbody = tag === "table" && !hasBody ?
 6078+ div.firstChild && div.firstChild.childNodes :
51276079
5128 - // String was a <table>, *may* have spurious <tbody>
5129 - var hasBody = rtbody.test(elem),
5130 - tbody = tag === "table" && !hasBody ?
5131 - div.firstChild && div.firstChild.childNodes :
 6080+ // String was a bare <thead> or <tfoot>
 6081+ wrap[1] === "<table>" && !hasBody ?
 6082+ div.childNodes :
 6083+ [];
51326084
5133 - // String was a bare <thead> or <tfoot>
5134 - wrap[1] === "<table>" && !hasBody ?
5135 - div.childNodes :
5136 - [];
5137 -
5138 - for ( var j = tbody.length - 1; j >= 0 ; --j ) {
5139 - if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
5140 - tbody[ j ].parentNode.removeChild( tbody[ j ] );
 6085+ for ( j = tbody.length - 1; j >= 0 ; --j ) {
 6086+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
 6087+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
 6088+ }
51416089 }
51426090 }
51436091
 6092+ // IE completely kills leading whitespace when innerHTML is used
 6093+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
 6094+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
 6095+ }
 6096+
 6097+ elem = div.childNodes;
51446098 }
 6099+ }
51456100
5146 - // IE completely kills leading whitespace when innerHTML is used
5147 - if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
5148 - div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
 6101+ // Resets defaultChecked for any radios and checkboxes
 6102+ // about to be appended to the DOM in IE 6/7 (#8060)
 6103+ var len;
 6104+ if ( !jQuery.support.appendChecked ) {
 6105+ if ( elem[0] && typeof (len = elem.length) === "number" ) {
 6106+ for ( j = 0; j < len; j++ ) {
 6107+ findInputs( elem[j] );
 6108+ }
 6109+ } else {
 6110+ findInputs( elem );
51496111 }
5150 -
5151 - elem = div.childNodes;
51526112 }
51536113
51546114 if ( elem.nodeType ) {
@@ -5158,13 +6118,18 @@
51596119 }
51606120
51616121 if ( fragment ) {
 6122+ checkScriptType = function( elem ) {
 6123+ return !elem.type || rscriptType.test( elem.type );
 6124+ };
51626125 for ( i = 0; ret[i]; i++ ) {
51636126 if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
51646127 scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
5165 -
 6128+
51666129 } else {
51676130 if ( ret[i].nodeType === 1 ) {
5168 - ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
 6131+ var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
 6132+
 6133+ ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
51696134 }
51706135 fragment.appendChild( ret[i] );
51716136 }
@@ -5173,40 +6138,45 @@
51746139
51756140 return ret;
51766141 },
5177 -
 6142+
51786143 cleanData: function( elems ) {
5179 - var data, id, cache = jQuery.cache,
5180 - special = jQuery.event.special,
 6144+ var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
51816145 deleteExpando = jQuery.support.deleteExpando;
5182 -
 6146+
51836147 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
51846148 if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
51856149 continue;
51866150 }
51876151
51886152 id = elem[ jQuery.expando ];
5189 -
 6153+
51906154 if ( id ) {
5191 - data = cache[ id ];
5192 -
 6155+ data = cache[ id ] && cache[ id ][ internalKey ];
 6156+
51936157 if ( data && data.events ) {
51946158 for ( var type in data.events ) {
51956159 if ( special[ type ] ) {
51966160 jQuery.event.remove( elem, type );
51976161
 6162+ // This is a shortcut to avoid jQuery.event.remove's overhead
51986163 } else {
51996164 jQuery.removeEvent( elem, type, data.handle );
52006165 }
52016166 }
 6167+
 6168+ // Null the DOM reference to avoid IE6/7/8 leak (#7054)
 6169+ if ( data.handle ) {
 6170+ data.handle.elem = null;
 6171+ }
52026172 }
5203 -
 6173+
52046174 if ( deleteExpando ) {
52056175 delete elem[ jQuery.expando ];
52066176
52076177 } else if ( elem.removeAttribute ) {
52086178 elem.removeAttribute( jQuery.expando );
52096179 }
5210 -
 6180+
52116181 delete cache[ id ];
52126182 }
52136183 }
@@ -5221,7 +6191,7 @@
52226192 dataType: "script"
52236193 });
52246194 } else {
5225 - jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
 6195+ jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
52266196 }
52276197
52286198 if ( elem.parentNode ) {
@@ -5235,9 +6205,12 @@
52366206 var ralpha = /alpha\([^)]*\)/i,
52376207 ropacity = /opacity=([^)]*)/,
52386208 rdashAlpha = /-([a-z])/ig,
5239 - rupper = /([A-Z])/g,
 6209+ // fixed for IE9, see #8346
 6210+ rupper = /([A-Z]|^ms)/g,
52406211 rnumpx = /^-?\d+(?:px)?$/i,
52416212 rnum = /^-?\d/,
 6213+ rrelNum = /^[+\-]=/,
 6214+ rrelNumFilter = /[^+\-\.\de]+/g,
52426215
52436216 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
52446217 cssWidth = [ "Left", "Right" ],
@@ -5288,7 +6261,9 @@
52896262 "fontWeight": true,
52906263 "opacity": true,
52916264 "zoom": true,
5292 - "lineHeight": true
 6265+ "lineHeight": true,
 6266+ "widows": true,
 6267+ "orphans": true
52936268 },
52946269
52956270 // Add in properties whose names you wish to fix before
@@ -5306,20 +6281,27 @@
53076282 }
53086283
53096284 // Make sure that we're working with the right name
5310 - var ret, origName = jQuery.camelCase( name ),
 6285+ var ret, type, origName = jQuery.camelCase( name ),
53116286 style = elem.style, hooks = jQuery.cssHooks[ origName ];
53126287
53136288 name = jQuery.cssProps[ origName ] || origName;
53146289
53156290 // Check if we're setting a value
53166291 if ( value !== undefined ) {
 6292+ type = typeof value;
 6293+
53176294 // Make sure that NaN and null values aren't set. See: #7116
5318 - if ( typeof value === "number" && isNaN( value ) || value == null ) {
 6295+ if ( type === "number" && isNaN( value ) || value == null ) {
53196296 return;
53206297 }
53216298
 6299+ // convert relative number strings (+= or -=) to relative numbers. #7345
 6300+ if ( type === "string" && rrelNum.test( value ) ) {
 6301+ value = +value.replace( rrelNumFilter, "" ) + parseFloat( jQuery.css( elem, name ) );
 6302+ }
 6303+
53226304 // If a number was passed in, add 'px' to the (except for certain CSS properties)
5323 - if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) {
 6305+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
53246306 value += "px";
53256307 }
53266308
@@ -5344,11 +6326,17 @@
53456327 },
53466328
53476329 css: function( elem, name, extra ) {
 6330+ var ret, hooks;
 6331+
53486332 // Make sure that we're working with the right name
5349 - var ret, origName = jQuery.camelCase( name ),
5350 - hooks = jQuery.cssHooks[ origName ];
 6333+ name = jQuery.camelCase( name );
 6334+ hooks = jQuery.cssHooks[ name ];
 6335+ name = jQuery.cssProps[ name ] || name;
53516336
5352 - name = jQuery.cssProps[ origName ] || origName;
 6337+ // cssFloat needs a special treatment
 6338+ if ( name === "cssFloat" ) {
 6339+ name = "float";
 6340+ }
53536341
53546342 // If a hook was provided get the computed value from there
53556343 if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
@@ -5356,7 +6344,7 @@
53576345
53586346 // Otherwise, if a way to get the computed value exists, use that
53596347 } else if ( curCSS ) {
5360 - return curCSS( elem, name, origName );
 6348+ return curCSS( elem, name );
53616349 }
53626350 },
53636351
@@ -5447,33 +6435,56 @@
54486436 jQuery.cssHooks.opacity = {
54496437 get: function( elem, computed ) {
54506438 // IE uses filters for opacity
5451 - return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ?
5452 - (parseFloat(RegExp.$1) / 100) + "" :
 6439+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
 6440+ ( parseFloat( RegExp.$1 ) / 100 ) + "" :
54536441 computed ? "1" : "";
54546442 },
54556443
54566444 set: function( elem, value ) {
5457 - var style = elem.style;
 6445+ var style = elem.style,
 6446+ currentStyle = elem.currentStyle;
54586447
54596448 // IE has trouble with opacity if it does not have layout
54606449 // Force it by setting the zoom level
54616450 style.zoom = 1;
54626451
54636452 // Set the alpha filter to set the opacity
5464 - var opacity = jQuery.isNaN(value) ?
 6453+ var opacity = jQuery.isNaN( value ) ?
54656454 "" :
54666455 "alpha(opacity=" + value * 100 + ")",
5467 - filter = style.filter || "";
 6456+ filter = currentStyle && currentStyle.filter || style.filter || "";
54686457
5469 - style.filter = ralpha.test(filter) ?
5470 - filter.replace(ralpha, opacity) :
5471 - style.filter + ' ' + opacity;
 6458+ style.filter = ralpha.test( filter ) ?
 6459+ filter.replace( ralpha, opacity ) :
 6460+ filter + " " + opacity;
54726461 }
54736462 };
54746463 }
54756464
 6465+jQuery(function() {
 6466+ // This hook cannot be added until DOM ready because the support test
 6467+ // for it is not run until after DOM ready
 6468+ if ( !jQuery.support.reliableMarginRight ) {
 6469+ jQuery.cssHooks.marginRight = {
 6470+ get: function( elem, computed ) {
 6471+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
 6472+ // Work around by temporarily setting element display to inline-block
 6473+ var ret;
 6474+ jQuery.swap( elem, { "display": "inline-block" }, function() {
 6475+ if ( computed ) {
 6476+ ret = curCSS( elem, "margin-right", "marginRight" );
 6477+ } else {
 6478+ ret = elem.style.marginRight;
 6479+ }
 6480+ });
 6481+ return ret;
 6482+ }
 6483+ };
 6484+ }
 6485+});
 6486+
54766487 if ( document.defaultView && document.defaultView.getComputedStyle ) {
5477 - getComputedStyle = function( elem, newName, name ) {
 6488+ getComputedStyle = function( elem, name ) {
54786489 var ret, defaultView, computedStyle;
54796490
54806491 name = name.replace( rupper, "-$1" ).toLowerCase();
@@ -5495,8 +6506,9 @@
54966507
54976508 if ( document.documentElement.currentStyle ) {
54986509 currentStyle = function( elem, name ) {
5499 - var left, rsLeft,
 6510+ var left,
55006511 ret = elem.currentStyle && elem.currentStyle[ name ],
 6512+ rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
55016513 style = elem.style;
55026514
55036515 // From the awesome hack by Dean Edwards
@@ -5507,16 +6519,19 @@
55086520 if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
55096521 // Remember the original values
55106522 left = style.left;
5511 - rsLeft = elem.runtimeStyle.left;
55126523
55136524 // Put in the new values to get a computed value out
5514 - elem.runtimeStyle.left = elem.currentStyle.left;
 6525+ if ( rsLeft ) {
 6526+ elem.runtimeStyle.left = elem.currentStyle.left;
 6527+ }
55156528 style.left = name === "fontSize" ? "1em" : (ret || 0);
55166529 ret = style.pixelLeft + "px";
55176530
55186531 // Revert the changed values
55196532 style.left = left;
5520 - elem.runtimeStyle.left = rsLeft;
 6533+ if ( rsLeft ) {
 6534+ elem.runtimeStyle.left = rsLeft;
 6535+ }
55216536 }
55226537
55236538 return ret === "" ? "auto" : ret;
@@ -5565,22 +6580,141 @@
55666581
55676582
55686583
5569 -var jsc = jQuery.now(),
5570 - rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
5571 - rselectTextarea = /^(?:select|textarea)/i,
 6584+var r20 = /%20/g,
 6585+ rbracket = /\[\]$/,
 6586+ rCRLF = /\r?\n/g,
 6587+ rhash = /#.*$/,
 6588+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
55726589 rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
 6590+ // #7653, #8125, #8152: local protocol detection
 6591+ rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|widget):$/,
55736592 rnoContent = /^(?:GET|HEAD)$/,
5574 - rbracket = /\[\]$/,
5575 - jsre = /\=\?(&|$)/,
 6593+ rprotocol = /^\/\//,
55766594 rquery = /\?/,
 6595+ rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
 6596+ rselectTextarea = /^(?:select|textarea)/i,
 6597+ rspacesAjax = /\s+/,
55776598 rts = /([?&])_=[^&]*/,
5578 - rurl = /^(\w+:)?\/\/([^\/?#]+)/,
5579 - r20 = /%20/g,
5580 - rhash = /#.*$/,
 6599+ rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
55816600
55826601 // Keep a copy of the old load method
5583 - _load = jQuery.fn.load;
 6602+ _load = jQuery.fn.load,
55846603
 6604+ /* Prefilters
 6605+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
 6606+ * 2) These are called:
 6607+ * - BEFORE asking for a transport
 6608+ * - AFTER param serialization (s.data is a string if s.processData is true)
 6609+ * 3) key is the dataType
 6610+ * 4) the catchall symbol "*" can be used
 6611+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
 6612+ */
 6613+ prefilters = {},
 6614+
 6615+ /* Transports bindings
 6616+ * 1) key is the dataType
 6617+ * 2) the catchall symbol "*" can be used
 6618+ * 3) selection will start with transport dataType and THEN go to "*" if needed
 6619+ */
 6620+ transports = {},
 6621+
 6622+ // Document location
 6623+ ajaxLocation,
 6624+
 6625+ // Document location segments
 6626+ ajaxLocParts;
 6627+
 6628+// #8138, IE may throw an exception when accessing
 6629+// a field from window.location if document.domain has been set
 6630+try {
 6631+ ajaxLocation = location.href;
 6632+} catch( e ) {
 6633+ // Use the href attribute of an A element
 6634+ // since IE will modify it given document.location
 6635+ ajaxLocation = document.createElement( "a" );
 6636+ ajaxLocation.href = "";
 6637+ ajaxLocation = ajaxLocation.href;
 6638+}
 6639+
 6640+// Segment location into parts
 6641+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
 6642+
 6643+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
 6644+function addToPrefiltersOrTransports( structure ) {
 6645+
 6646+ // dataTypeExpression is optional and defaults to "*"
 6647+ return function( dataTypeExpression, func ) {
 6648+
 6649+ if ( typeof dataTypeExpression !== "string" ) {
 6650+ func = dataTypeExpression;
 6651+ dataTypeExpression = "*";
 6652+ }
 6653+
 6654+ if ( jQuery.isFunction( func ) ) {
 6655+ var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
 6656+ i = 0,
 6657+ length = dataTypes.length,
 6658+ dataType,
 6659+ list,
 6660+ placeBefore;
 6661+
 6662+ // For each dataType in the dataTypeExpression
 6663+ for(; i < length; i++ ) {
 6664+ dataType = dataTypes[ i ];
 6665+ // We control if we're asked to add before
 6666+ // any existing element
 6667+ placeBefore = /^\+/.test( dataType );
 6668+ if ( placeBefore ) {
 6669+ dataType = dataType.substr( 1 ) || "*";
 6670+ }
 6671+ list = structure[ dataType ] = structure[ dataType ] || [];
 6672+ // then we add to the structure accordingly
 6673+ list[ placeBefore ? "unshift" : "push" ]( func );
 6674+ }
 6675+ }
 6676+ };
 6677+}
 6678+
 6679+// Base inspection function for prefilters and transports
 6680+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
 6681+ dataType /* internal */, inspected /* internal */ ) {
 6682+
 6683+ dataType = dataType || options.dataTypes[ 0 ];
 6684+ inspected = inspected || {};
 6685+
 6686+ inspected[ dataType ] = true;
 6687+
 6688+ var list = structure[ dataType ],
 6689+ i = 0,
 6690+ length = list ? list.length : 0,
 6691+ executeOnly = ( structure === prefilters ),
 6692+ selection;
 6693+
 6694+ for(; i < length && ( executeOnly || !selection ); i++ ) {
 6695+ selection = list[ i ]( options, originalOptions, jqXHR );
 6696+ // If we got redirected to another dataType
 6697+ // we try there if executing only and not done already
 6698+ if ( typeof selection === "string" ) {
 6699+ if ( !executeOnly || inspected[ selection ] ) {
 6700+ selection = undefined;
 6701+ } else {
 6702+ options.dataTypes.unshift( selection );
 6703+ selection = inspectPrefiltersOrTransports(
 6704+ structure, options, originalOptions, jqXHR, selection, inspected );
 6705+ }
 6706+ }
 6707+ }
 6708+ // If we're only executing or nothing was selected
 6709+ // we try the catchall dataType if not done already
 6710+ if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
 6711+ selection = inspectPrefiltersOrTransports(
 6712+ structure, options, originalOptions, jqXHR, "*", inspected );
 6713+ }
 6714+ // unnecessary when only executing (prefilters)
 6715+ // but it'll be ignored by the caller in that case
 6716+ return selection;
 6717+}
 6718+
55856719 jQuery.fn.extend({
55866720 load: function( url, params, callback ) {
55876721 if ( typeof url !== "string" && _load ) {
@@ -5591,10 +6725,10 @@
55926726 return this;
55936727 }
55946728
5595 - var off = url.indexOf(" ");
 6729+ var off = url.indexOf( " " );
55966730 if ( off >= 0 ) {
5597 - var selector = url.slice(off, url.length);
5598 - url = url.slice(0, off);
 6731+ var selector = url.slice( off, url.length );
 6732+ url = url.slice( 0, off );
55996733 }
56006734
56016735 // Default to a GET request
@@ -5606,7 +6740,7 @@
56076741 if ( jQuery.isFunction( params ) ) {
56086742 // We assume that it's the callback
56096743 callback = params;
5610 - params = null;
 6744+ params = undefined;
56116745
56126746 // Otherwise, build a param string
56136747 } else if ( typeof params === "object" ) {
@@ -5623,26 +6757,34 @@
56246758 type: type,
56256759 dataType: "html",
56266760 data: params,
5627 - complete: function( res, status ) {
 6761+ // Complete callback (responseText is used internally)
 6762+ complete: function( jqXHR, status, responseText ) {
 6763+ // Store the response as specified by the jqXHR object
 6764+ responseText = jqXHR.responseText;
56286765 // If successful, inject the HTML into all the matched elements
5629 - if ( status === "success" || status === "notmodified" ) {
 6766+ if ( jqXHR.isResolved() ) {
 6767+ // #4825: Get the actual response in case
 6768+ // a dataFilter is present in ajaxSettings
 6769+ jqXHR.done(function( r ) {
 6770+ responseText = r;
 6771+ });
56306772 // See if a selector was specified
56316773 self.html( selector ?
56326774 // Create a dummy div to hold the results
56336775 jQuery("<div>")
56346776 // inject the contents of the document in, removing the scripts
56356777 // to avoid any 'Permission Denied' errors in IE
5636 - .append(res.responseText.replace(rscript, ""))
 6778+ .append(responseText.replace(rscript, ""))
56376779
56386780 // Locate the specified elements
56396781 .find(selector) :
56406782
56416783 // If not, just inject the full result
5642 - res.responseText );
 6784+ responseText );
56436785 }
56446786
56456787 if ( callback ) {
5646 - self.each( callback, [res.responseText, status, res] );
 6788+ self.each( callback, [ responseText, status, jqXHR ] );
56476789 }
56486790 }
56496791 });
@@ -5651,88 +6793,94 @@
56526794 },
56536795
56546796 serialize: function() {
5655 - return jQuery.param(this.serializeArray());
 6797+ return jQuery.param( this.serializeArray() );
56566798 },
56576799
56586800 serializeArray: function() {
5659 - return this.map(function() {
5660 - return this.elements ? jQuery.makeArray(this.elements) : this;
 6801+ return this.map(function(){
 6802+ return this.elements ? jQuery.makeArray( this.elements ) : this;
56616803 })
5662 - .filter(function() {
 6804+ .filter(function(){
56636805 return this.name && !this.disabled &&
5664 - (this.checked || rselectTextarea.test(this.nodeName) ||
5665 - rinput.test(this.type));
 6806+ ( this.checked || rselectTextarea.test( this.nodeName ) ||
 6807+ rinput.test( this.type ) );
56666808 })
5667 - .map(function( i, elem ) {
5668 - var val = jQuery(this).val();
 6809+ .map(function( i, elem ){
 6810+ var val = jQuery( this ).val();
56696811
56706812 return val == null ?
56716813 null :
5672 - jQuery.isArray(val) ?
5673 - jQuery.map( val, function( val, i ) {
5674 - return { name: elem.name, value: val };
 6814+ jQuery.isArray( val ) ?
 6815+ jQuery.map( val, function( val, i ){
 6816+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
56756817 }) :
5676 - { name: elem.name, value: val };
 6818+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
56776819 }).get();
56786820 }
56796821 });
56806822
56816823 // Attach a bunch of functions for handling common AJAX events
5682 -jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
5683 - jQuery.fn[o] = function( f ) {
5684 - return this.bind(o, f);
 6824+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
 6825+ jQuery.fn[ o ] = function( f ){
 6826+ return this.bind( o, f );
56856827 };
56866828 });
56876829
5688 -jQuery.extend({
5689 - get: function( url, data, callback, type ) {
5690 - // shift arguments if data argument was omited
 6830+jQuery.each( [ "get", "post" ], function( i, method ) {
 6831+ jQuery[ method ] = function( url, data, callback, type ) {
 6832+ // shift arguments if data argument was omitted
56916833 if ( jQuery.isFunction( data ) ) {
56926834 type = type || callback;
56936835 callback = data;
5694 - data = null;
 6836+ data = undefined;
56956837 }
56966838
56976839 return jQuery.ajax({
5698 - type: "GET",
 6840+ type: method,
56996841 url: url,
57006842 data: data,
57016843 success: callback,
57026844 dataType: type
57036845 });
5704 - },
 6846+ };
 6847+});
57056848
 6849+jQuery.extend({
 6850+
57066851 getScript: function( url, callback ) {
5707 - return jQuery.get(url, null, callback, "script");
 6852+ return jQuery.get( url, undefined, callback, "script" );
57086853 },
57096854
57106855 getJSON: function( url, data, callback ) {
5711 - return jQuery.get(url, data, callback, "json");
 6856+ return jQuery.get( url, data, callback, "json" );
57126857 },
57136858
5714 - post: function( url, data, callback, type ) {
5715 - // shift arguments if data argument was omited
5716 - if ( jQuery.isFunction( data ) ) {
5717 - type = type || callback;
5718 - callback = data;
5719 - data = {};
 6859+ // Creates a full fledged settings object into target
 6860+ // with both ajaxSettings and settings fields.
 6861+ // If target is omitted, writes into ajaxSettings.
 6862+ ajaxSetup: function ( target, settings ) {
 6863+ if ( !settings ) {
 6864+ // Only one parameter, we extend ajaxSettings
 6865+ settings = target;
 6866+ target = jQuery.extend( true, jQuery.ajaxSettings, settings );
 6867+ } else {
 6868+ // target was provided, we extend into it
 6869+ jQuery.extend( true, target, jQuery.ajaxSettings, settings );
57206870 }
5721 -
5722 - return jQuery.ajax({
5723 - type: "POST",
5724 - url: url,
5725 - data: data,
5726 - success: callback,
5727 - dataType: type
5728 - });
 6871+ // Flatten fields we don't want deep extended
 6872+ for( var field in { context: 1, url: 1 } ) {
 6873+ if ( field in settings ) {
 6874+ target[ field ] = settings[ field ];
 6875+ } else if( field in jQuery.ajaxSettings ) {
 6876+ target[ field ] = jQuery.ajaxSettings[ field ];
 6877+ }
 6878+ }
 6879+ return target;
57296880 },
57306881
5731 - ajaxSetup: function( settings ) {
5732 - jQuery.extend( jQuery.ajaxSettings, settings );
5733 - },
5734 -
57356882 ajaxSettings: {
5736 - url: location.href,
 6883+ url: ajaxLocation,
 6884+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
57376885 global: true,
57386886 type: "GET",
57396887 contentType: "application/x-www-form-urlencoded",
@@ -5741,332 +6889,434 @@
57426890 /*
57436891 timeout: 0,
57446892 data: null,
 6893+ dataType: null,
57456894 username: null,
57466895 password: null,
 6896+ cache: null,
57476897 traditional: false,
 6898+ headers: {},
57486899 */
5749 - // This function can be overriden by calling jQuery.ajaxSetup
5750 - xhr: function() {
5751 - return new window.XMLHttpRequest();
5752 - },
 6900+
57536901 accepts: {
57546902 xml: "application/xml, text/xml",
57556903 html: "text/html",
5756 - script: "text/javascript, application/javascript",
 6904+ text: "text/plain",
57576905 json: "application/json, text/javascript",
5758 - text: "text/plain",
5759 - _default: "*/*"
5760 - }
5761 - },
 6906+ "*": "*/*"
 6907+ },
57626908
5763 - ajax: function( origSettings ) {
5764 - var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings),
5765 - jsonp, status, data, type = s.type.toUpperCase(), noContent = rnoContent.test(type);
 6909+ contents: {
 6910+ xml: /xml/,
 6911+ html: /html/,
 6912+ json: /json/
 6913+ },
57666914
5767 - s.url = s.url.replace( rhash, "" );
 6915+ responseFields: {
 6916+ xml: "responseXML",
 6917+ text: "responseText"
 6918+ },
57686919
5769 - // Use original (not extended) context object if it was provided
5770 - s.context = origSettings && origSettings.context != null ? origSettings.context : s;
 6920+ // List of data converters
 6921+ // 1) key format is "source_type destination_type" (a single space in-between)
 6922+ // 2) the catchall symbol "*" can be used for source_type
 6923+ converters: {
57716924
5772 - // convert data if not already a string
5773 - if ( s.data && s.processData && typeof s.data !== "string" ) {
5774 - s.data = jQuery.param( s.data, s.traditional );
 6925+ // Convert anything to text
 6926+ "* text": window.String,
 6927+
 6928+ // Text to html (true = no transformation)
 6929+ "text html": true,
 6930+
 6931+ // Evaluate text as a json expression
 6932+ "text json": jQuery.parseJSON,
 6933+
 6934+ // Parse text as xml
 6935+ "text xml": jQuery.parseXML
57756936 }
 6937+ },
57766938
5777 - // Handle JSONP Parameter Callbacks
5778 - if ( s.dataType === "jsonp" ) {
5779 - if ( type === "GET" ) {
5780 - if ( !jsre.test( s.url ) ) {
5781 - s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
5782 - }
5783 - } else if ( !s.data || !jsre.test(s.data) ) {
5784 - s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
5785 - }
5786 - s.dataType = "json";
 6939+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
 6940+ ajaxTransport: addToPrefiltersOrTransports( transports ),
 6941+
 6942+ // Main method
 6943+ ajax: function( url, options ) {
 6944+
 6945+ // If url is an object, simulate pre-1.5 signature
 6946+ if ( typeof url === "object" ) {
 6947+ options = url;
 6948+ url = undefined;
57876949 }
57886950
5789 - // Build temporary JSONP function
5790 - if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
5791 - jsonp = s.jsonpCallback || ("jsonp" + jsc++);
 6951+ // Force options to be an object
 6952+ options = options || {};
57926953
5793 - // Replace the =? sequence both in the query string and the data
5794 - if ( s.data ) {
5795 - s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
5796 - }
 6954+ var // Create the final options object
 6955+ s = jQuery.ajaxSetup( {}, options ),
 6956+ // Callbacks context
 6957+ callbackContext = s.context || s,
 6958+ // Context for global events
 6959+ // It's the callbackContext if one was provided in the options
 6960+ // and if it's a DOM node or a jQuery collection
 6961+ globalEventContext = callbackContext !== s &&
 6962+ ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
 6963+ jQuery( callbackContext ) : jQuery.event,
 6964+ // Deferreds
 6965+ deferred = jQuery.Deferred(),
 6966+ completeDeferred = jQuery._Deferred(),
 6967+ // Status-dependent callbacks
 6968+ statusCode = s.statusCode || {},
 6969+ // ifModified key
 6970+ ifModifiedKey,
 6971+ // Headers (they are sent all at once)
 6972+ requestHeaders = {},
 6973+ requestHeadersNames = {},
 6974+ // Response headers
 6975+ responseHeadersString,
 6976+ responseHeaders,
 6977+ // transport
 6978+ transport,
 6979+ // timeout handle
 6980+ timeoutTimer,
 6981+ // Cross-domain detection vars
 6982+ parts,
 6983+ // The jqXHR state
 6984+ state = 0,
 6985+ // To know if global events are to be dispatched
 6986+ fireGlobals,
 6987+ // Loop variable
 6988+ i,
 6989+ // Fake xhr
 6990+ jqXHR = {
57976991
5798 - s.url = s.url.replace(jsre, "=" + jsonp + "$1");
 6992+ readyState: 0,
57996993
5800 - // We need to make sure
5801 - // that a JSONP style response is executed properly
5802 - s.dataType = "script";
 6994+ // Caches the header
 6995+ setRequestHeader: function( name, value ) {
 6996+ if ( !state ) {
 6997+ var lname = name.toLowerCase();
 6998+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
 6999+ requestHeaders[ name ] = value;
 7000+ }
 7001+ return this;
 7002+ },
58037003
5804 - // Handle JSONP-style loading
5805 - var customJsonp = window[ jsonp ];
 7004+ // Raw string
 7005+ getAllResponseHeaders: function() {
 7006+ return state === 2 ? responseHeadersString : null;
 7007+ },
58067008
5807 - window[ jsonp ] = function( tmp ) {
5808 - if ( jQuery.isFunction( customJsonp ) ) {
5809 - customJsonp( tmp );
 7009+ // Builds headers hashtable if needed
 7010+ getResponseHeader: function( key ) {
 7011+ var match;
 7012+ if ( state === 2 ) {
 7013+ if ( !responseHeaders ) {
 7014+ responseHeaders = {};
 7015+ while( ( match = rheaders.exec( responseHeadersString ) ) ) {
 7016+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
 7017+ }
 7018+ }
 7019+ match = responseHeaders[ key.toLowerCase() ];
 7020+ }
 7021+ return match === undefined ? null : match;
 7022+ },
58107023
5811 - } else {
5812 - // Garbage collect
5813 - window[ jsonp ] = undefined;
 7024+ // Overrides response content-type header
 7025+ overrideMimeType: function( type ) {
 7026+ if ( !state ) {
 7027+ s.mimeType = type;
 7028+ }
 7029+ return this;
 7030+ },
58147031
5815 - try {
5816 - delete window[ jsonp ];
5817 - } catch( jsonpError ) {}
 7032+ // Cancel the request
 7033+ abort: function( statusText ) {
 7034+ statusText = statusText || "abort";
 7035+ if ( transport ) {
 7036+ transport.abort( statusText );
 7037+ }
 7038+ done( 0, statusText );
 7039+ return this;
58187040 }
5819 -
5820 - data = tmp;
5821 - jQuery.handleSuccess( s, xhr, status, data );
5822 - jQuery.handleComplete( s, xhr, status, data );
5823 -
5824 - if ( head ) {
5825 - head.removeChild( script );
5826 - }
58277041 };
5828 - }
58297042
5830 - if ( s.dataType === "script" && s.cache === null ) {
5831 - s.cache = false;
5832 - }
 7043+ // Callback for when everything is done
 7044+ // It is defined here because jslint complains if it is declared
 7045+ // at the end of the function (which would be more logical and readable)
 7046+ function done( status, statusText, responses, headers ) {
58337047
5834 - if ( s.cache === false && noContent ) {
5835 - var ts = jQuery.now();
 7048+ // Called once
 7049+ if ( state === 2 ) {
 7050+ return;
 7051+ }
58367052
5837 - // try replacing _= if it is there
5838 - var ret = s.url.replace(rts, "$1_=" + ts);
 7053+ // State is "done" now
 7054+ state = 2;
58397055
5840 - // if nothing was replaced, add timestamp to the end
5841 - s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
5842 - }
 7056+ // Clear timeout if it exists
 7057+ if ( timeoutTimer ) {
 7058+ clearTimeout( timeoutTimer );
 7059+ }
58437060
5844 - // If data is available, append data to url for GET/HEAD requests
5845 - if ( s.data && noContent ) {
5846 - s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
5847 - }
 7061+ // Dereference transport for early garbage collection
 7062+ // (no matter how long the jqXHR object will be used)
 7063+ transport = undefined;
58487064
5849 - // Watch for a new set of requests
5850 - if ( s.global && jQuery.active++ === 0 ) {
5851 - jQuery.event.trigger( "ajaxStart" );
5852 - }
 7065+ // Cache response headers
 7066+ responseHeadersString = headers || "";
58537067
5854 - // Matches an absolute URL, and saves the domain
5855 - var parts = rurl.exec( s.url ),
5856 - remote = parts && (parts[1] && parts[1].toLowerCase() !== location.protocol || parts[2].toLowerCase() !== location.host);
 7068+ // Set readyState
 7069+ jqXHR.readyState = status ? 4 : 0;
58577070
5858 - // If we're requesting a remote document
5859 - // and trying to load JSON or Script with a GET
5860 - if ( s.dataType === "script" && type === "GET" && remote ) {
5861 - var head = document.getElementsByTagName("head")[0] || document.documentElement;
5862 - var script = document.createElement("script");
5863 - if ( s.scriptCharset ) {
5864 - script.charset = s.scriptCharset;
5865 - }
5866 - script.src = s.url;
 7071+ var isSuccess,
 7072+ success,
 7073+ error,
 7074+ response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
 7075+ lastModified,
 7076+ etag;
58677077
5868 - // Handle Script loading
5869 - if ( !jsonp ) {
5870 - var done = false;
 7078+ // If successful, handle type chaining
 7079+ if ( status >= 200 && status < 300 || status === 304 ) {
58717080
5872 - // Attach handlers for all browsers
5873 - script.onload = script.onreadystatechange = function() {
5874 - if ( !done && (!this.readyState ||
5875 - this.readyState === "loaded" || this.readyState === "complete") ) {
5876 - done = true;
5877 - jQuery.handleSuccess( s, xhr, status, data );
5878 - jQuery.handleComplete( s, xhr, status, data );
 7081+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
 7082+ if ( s.ifModified ) {
58797083
5880 - // Handle memory leak in IE
5881 - script.onload = script.onreadystatechange = null;
5882 - if ( head && script.parentNode ) {
5883 - head.removeChild( script );
5884 - }
 7084+ if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
 7085+ jQuery.lastModified[ ifModifiedKey ] = lastModified;
58857086 }
5886 - };
5887 - }
 7087+ if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
 7088+ jQuery.etag[ ifModifiedKey ] = etag;
 7089+ }
 7090+ }
58887091
5889 - // Use insertBefore instead of appendChild to circumvent an IE6 bug.
5890 - // This arises when a base node is used (#2709 and #4378).
5891 - head.insertBefore( script, head.firstChild );
 7092+ // If not modified
 7093+ if ( status === 304 ) {
58927094
5893 - // We handle everything using the script element injection
5894 - return undefined;
5895 - }
 7095+ statusText = "notmodified";
 7096+ isSuccess = true;
58967097
5897 - var requestDone = false;
 7098+ // If we have data
 7099+ } else {
58987100
5899 - // Create the request object
5900 - var xhr = s.xhr();
 7101+ try {
 7102+ success = ajaxConvert( s, response );
 7103+ statusText = "success";
 7104+ isSuccess = true;
 7105+ } catch(e) {
 7106+ // We have a parsererror
 7107+ statusText = "parsererror";
 7108+ error = e;
 7109+ }
 7110+ }
 7111+ } else {
 7112+ // We extract error from statusText
 7113+ // then normalize statusText and status for non-aborts
 7114+ error = statusText;
 7115+ if( !statusText || status ) {
 7116+ statusText = "error";
 7117+ if ( status < 0 ) {
 7118+ status = 0;
 7119+ }
 7120+ }
 7121+ }
59017122
5902 - if ( !xhr ) {
5903 - return;
5904 - }
 7123+ // Set data for the fake xhr object
 7124+ jqXHR.status = status;
 7125+ jqXHR.statusText = statusText;
59057126
5906 - // Open the socket
5907 - // Passing null username, generates a login popup on Opera (#2865)
5908 - if ( s.username ) {
5909 - xhr.open(type, s.url, s.async, s.username, s.password);
5910 - } else {
5911 - xhr.open(type, s.url, s.async);
5912 - }
 7127+ // Success/Error
 7128+ if ( isSuccess ) {
 7129+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
 7130+ } else {
 7131+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
 7132+ }
59137133
5914 - // Need an extra try/catch for cross domain requests in Firefox 3
5915 - try {
5916 - // Set content-type if data specified and content-body is valid for this type
5917 - if ( (s.data != null && !noContent) || (origSettings && origSettings.contentType) ) {
5918 - xhr.setRequestHeader("Content-Type", s.contentType);
 7134+ // Status-dependent callbacks
 7135+ jqXHR.statusCode( statusCode );
 7136+ statusCode = undefined;
 7137+
 7138+ if ( fireGlobals ) {
 7139+ globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
 7140+ [ jqXHR, s, isSuccess ? success : error ] );
59197141 }
59207142
5921 - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
5922 - if ( s.ifModified ) {
5923 - if ( jQuery.lastModified[s.url] ) {
5924 - xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
5925 - }
 7143+ // Complete
 7144+ completeDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );
59267145
5927 - if ( jQuery.etag[s.url] ) {
5928 - xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
 7146+ if ( fireGlobals ) {
 7147+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s] );
 7148+ // Handle the global AJAX counter
 7149+ if ( !( --jQuery.active ) ) {
 7150+ jQuery.event.trigger( "ajaxStop" );
59297151 }
59307152 }
 7153+ }
59317154
5932 - // Set header so the called script knows that it's an XMLHttpRequest
5933 - // Only send the header if it's not a remote XHR
5934 - if ( !remote ) {
5935 - xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
 7155+ // Attach deferreds
 7156+ deferred.promise( jqXHR );
 7157+ jqXHR.success = jqXHR.done;
 7158+ jqXHR.error = jqXHR.fail;
 7159+ jqXHR.complete = completeDeferred.done;
 7160+
 7161+ // Status-dependent callbacks
 7162+ jqXHR.statusCode = function( map ) {
 7163+ if ( map ) {
 7164+ var tmp;
 7165+ if ( state < 2 ) {
 7166+ for( tmp in map ) {
 7167+ statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
 7168+ }
 7169+ } else {
 7170+ tmp = map[ jqXHR.status ];
 7171+ jqXHR.then( tmp, tmp );
 7172+ }
59367173 }
 7174+ return this;
 7175+ };
59377176
5938 - // Set the Accepts header for the server, depending on the dataType
5939 - xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
5940 - s.accepts[ s.dataType ] + ", */*; q=0.01" :
5941 - s.accepts._default );
5942 - } catch( headerError ) {}
 7177+ // Remove hash character (#7531: and string promotion)
 7178+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
 7179+ // We also use the url parameter if available
 7180+ s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
59437181
5944 - // Allow custom headers/mimetypes and early abort
5945 - if ( s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false ) {
5946 - // Handle the global AJAX counter
5947 - if ( s.global && jQuery.active-- === 1 ) {
5948 - jQuery.event.trigger( "ajaxStop" );
5949 - }
 7182+ // Extract dataTypes list
 7183+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
59507184
5951 - // close opended socket
5952 - xhr.abort();
5953 - return false;
 7185+ // Determine if a cross-domain request is in order
 7186+ if ( s.crossDomain == null ) {
 7187+ parts = rurl.exec( s.url.toLowerCase() );
 7188+ s.crossDomain = !!( parts &&
 7189+ ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
 7190+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
 7191+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
 7192+ );
59547193 }
59557194
5956 - if ( s.global ) {
5957 - jQuery.triggerGlobal( s, "ajaxSend", [xhr, s] );
 7195+ // Convert data if not already a string
 7196+ if ( s.data && s.processData && typeof s.data !== "string" ) {
 7197+ s.data = jQuery.param( s.data, s.traditional );
59587198 }
59597199
5960 - // Wait for a response to come back
5961 - var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
5962 - // The request was aborted
5963 - if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
5964 - // Opera doesn't call onreadystatechange before this point
5965 - // so we simulate the call
5966 - if ( !requestDone ) {
5967 - jQuery.handleComplete( s, xhr, status, data );
5968 - }
 7200+ // Apply prefilters
 7201+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
59697202
5970 - requestDone = true;
5971 - if ( xhr ) {
5972 - xhr.onreadystatechange = jQuery.noop;
5973 - }
 7203+ // If request was aborted inside a prefiler, stop there
 7204+ if ( state === 2 ) {
 7205+ return false;
 7206+ }
59747207
5975 - // The transfer is complete and the data is available, or the request timed out
5976 - } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
5977 - requestDone = true;
5978 - xhr.onreadystatechange = jQuery.noop;
 7208+ // We can fire global events as of now if asked to
 7209+ fireGlobals = s.global;
59797210
5980 - status = isTimeout === "timeout" ?
5981 - "timeout" :
5982 - !jQuery.httpSuccess( xhr ) ?
5983 - "error" :
5984 - s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
5985 - "notmodified" :
5986 - "success";
 7211+ // Uppercase the type
 7212+ s.type = s.type.toUpperCase();
59877213
5988 - var errMsg;
 7214+ // Determine if request has content
 7215+ s.hasContent = !rnoContent.test( s.type );
59897216
5990 - if ( status === "success" ) {
5991 - // Watch for, and catch, XML document parse errors
5992 - try {
5993 - // process the data (runs the xml through httpData regardless of callback)
5994 - data = jQuery.httpData( xhr, s.dataType, s );
5995 - } catch( parserError ) {
5996 - status = "parsererror";
5997 - errMsg = parserError;
5998 - }
5999 - }
 7217+ // Watch for a new set of requests
 7218+ if ( fireGlobals && jQuery.active++ === 0 ) {
 7219+ jQuery.event.trigger( "ajaxStart" );
 7220+ }
60007221
6001 - // Make sure that the request was successful or notmodified
6002 - if ( status === "success" || status === "notmodified" ) {
6003 - // JSONP handles its own success callback
6004 - if ( !jsonp ) {
6005 - jQuery.handleSuccess( s, xhr, status, data );
6006 - }
6007 - } else {
6008 - jQuery.handleError( s, xhr, status, errMsg );
6009 - }
 7222+ // More options handling for requests with no content
 7223+ if ( !s.hasContent ) {
60107224
6011 - // Fire the complete handlers
6012 - if ( !jsonp ) {
6013 - jQuery.handleComplete( s, xhr, status, data );
6014 - }
 7225+ // If data is available, append data to url
 7226+ if ( s.data ) {
 7227+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
 7228+ }
60157229
6016 - if ( isTimeout === "timeout" ) {
6017 - xhr.abort();
6018 - }
 7230+ // Get ifModifiedKey before adding the anti-cache parameter
 7231+ ifModifiedKey = s.url;
60197232
6020 - // Stop memory leaks
6021 - if ( s.async ) {
6022 - xhr = null;
6023 - }
 7233+ // Add anti-cache in url if needed
 7234+ if ( s.cache === false ) {
 7235+
 7236+ var ts = jQuery.now(),
 7237+ // try replacing _= if it is there
 7238+ ret = s.url.replace( rts, "$1_=" + ts );
 7239+
 7240+ // if nothing was replaced, add timestamp to the end
 7241+ s.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
60247242 }
6025 - };
 7243+ }
60267244
6027 - // Override the abort handler, if we can (IE 6 doesn't allow it, but that's OK)
6028 - // Opera doesn't fire onreadystatechange at all on abort
6029 - try {
6030 - var oldAbort = xhr.abort;
6031 - xhr.abort = function() {
6032 - if ( xhr ) {
6033 - // oldAbort has no call property in IE7 so
6034 - // just do it this way, which works in all
6035 - // browsers
6036 - Function.prototype.call.call( oldAbort, xhr );
6037 - }
 7245+ // Set the correct header, if data is being sent
 7246+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
 7247+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
 7248+ }
60387249
6039 - onreadystatechange( "abort" );
6040 - };
6041 - } catch( abortError ) {}
 7250+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
 7251+ if ( s.ifModified ) {
 7252+ ifModifiedKey = ifModifiedKey || s.url;
 7253+ if ( jQuery.lastModified[ ifModifiedKey ] ) {
 7254+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
 7255+ }
 7256+ if ( jQuery.etag[ ifModifiedKey ] ) {
 7257+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
 7258+ }
 7259+ }
60427260
6043 - // Timeout checker
6044 - if ( s.async && s.timeout > 0 ) {
6045 - setTimeout(function() {
6046 - // Check to see if the request is still happening
6047 - if ( xhr && !requestDone ) {
6048 - onreadystatechange( "timeout" );
6049 - }
6050 - }, s.timeout);
 7261+ // Set the Accepts header for the server, depending on the dataType
 7262+ jqXHR.setRequestHeader(
 7263+ "Accept",
 7264+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
 7265+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
 7266+ s.accepts[ "*" ]
 7267+ );
 7268+
 7269+ // Check for headers option
 7270+ for ( i in s.headers ) {
 7271+ jqXHR.setRequestHeader( i, s.headers[ i ] );
60517272 }
60527273
6053 - // Send the data
6054 - try {
6055 - xhr.send( noContent || s.data == null ? null : s.data );
 7274+ // Allow custom headers/mimetypes and early abort
 7275+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
 7276+ // Abort if not done already
 7277+ jqXHR.abort();
 7278+ return false;
60567279
6057 - } catch( sendError ) {
6058 - jQuery.handleError( s, xhr, null, sendError );
 7280+ }
60597281
6060 - // Fire the complete handlers
6061 - jQuery.handleComplete( s, xhr, status, data );
 7282+ // Install callbacks on deferreds
 7283+ for ( i in { success: 1, error: 1, complete: 1 } ) {
 7284+ jqXHR[ i ]( s[ i ] );
60627285 }
60637286
6064 - // firefox 1.5 doesn't fire statechange for sync requests
6065 - if ( !s.async ) {
6066 - onreadystatechange();
 7287+ // Get transport
 7288+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
 7289+
 7290+ // If no transport, we auto-abort
 7291+ if ( !transport ) {
 7292+ done( -1, "No Transport" );
 7293+ } else {
 7294+ jqXHR.readyState = 1;
 7295+ // Send global event
 7296+ if ( fireGlobals ) {
 7297+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
 7298+ }
 7299+ // Timeout
 7300+ if ( s.async && s.timeout > 0 ) {
 7301+ timeoutTimer = setTimeout( function(){
 7302+ jqXHR.abort( "timeout" );
 7303+ }, s.timeout );
 7304+ }
 7305+
 7306+ try {
 7307+ state = 1;
 7308+ transport.send( requestHeaders, done );
 7309+ } catch (e) {
 7310+ // Propagate exception as error if not done
 7311+ if ( status < 2 ) {
 7312+ done( -1, e );
 7313+ // Simply rethrow otherwise
 7314+ } else {
 7315+ jQuery.error( e );
 7316+ }
 7317+ }
60677318 }
60687319
6069 - // return XMLHttpRequest to allow aborting the request etc.
6070 - return xhr;
 7320+ return jqXHR;
60717321 },
60727322
60737323 // Serialize an array of form elements or a set of
@@ -6075,37 +7325,37 @@
60767326 var s = [],
60777327 add = function( key, value ) {
60787328 // If value is a function, invoke it and return its value
6079 - value = jQuery.isFunction(value) ? value() : value;
6080 - s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
 7329+ value = jQuery.isFunction( value ) ? value() : value;
 7330+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
60817331 };
6082 -
 7332+
60837333 // Set traditional to true for jQuery <= 1.3.2 behavior.
60847334 if ( traditional === undefined ) {
60857335 traditional = jQuery.ajaxSettings.traditional;
60867336 }
6087 -
 7337+
60887338 // If an array was passed in, assume that it is an array of form elements.
6089 - if ( jQuery.isArray(a) || a.jquery ) {
 7339+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
60907340 // Serialize the form elements
60917341 jQuery.each( a, function() {
60927342 add( this.name, this.value );
60937343 });
6094 -
 7344+
60957345 } else {
60967346 // If traditional, encode the "old" way (the way 1.3.2 or older
60977347 // did it), otherwise encode params recursively.
60987348 for ( var prefix in a ) {
6099 - buildParams( prefix, a[prefix], traditional, add );
 7349+ buildParams( prefix, a[ prefix ], traditional, add );
61007350 }
61017351 }
61027352
61037353 // Return the resulting serialization
6104 - return s.join("&").replace(r20, "+");
 7354+ return s.join( "&" ).replace( r20, "+" );
61057355 }
61067356 });
61077357
61087358 function buildParams( prefix, obj, traditional, add ) {
6109 - if ( jQuery.isArray(obj) && obj.length ) {
 7359+ if ( jQuery.isArray( obj ) ) {
61107360 // Serialize array item.
61117361 jQuery.each( obj, function( i, v ) {
61127362 if ( traditional || rbracket.test( prefix ) ) {
@@ -6123,18 +7373,13 @@
61247374 buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
61257375 }
61267376 });
6127 -
 7377+
61287378 } else if ( !traditional && obj != null && typeof obj === "object" ) {
6129 - if ( jQuery.isEmptyObject( obj ) ) {
6130 - add( prefix, "" );
6131 -
61327379 // Serialize object item.
6133 - } else {
6134 - jQuery.each( obj, function( k, v ) {
6135 - buildParams( prefix + "[" + k + "]", v, traditional, add );
6136 - });
 7380+ for ( var name in obj ) {
 7381+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
61377382 }
6138 -
 7383+
61397384 } else {
61407385 // Serialize scalar item.
61417386 add( prefix, obj );
@@ -6150,143 +7395,557 @@
61517396
61527397 // Last-Modified header cache for next request
61537398 lastModified: {},
6154 - etag: {},
 7399+ etag: {}
61557400
6156 - handleError: function( s, xhr, status, e ) {
6157 - // If a local callback was specified, fire it
6158 - if ( s.error ) {
6159 - s.error.call( s.context, xhr, status, e );
6160 - }
 7401+});
61617402
6162 - // Fire the global callback
6163 - if ( s.global ) {
6164 - jQuery.triggerGlobal( s, "ajaxError", [xhr, s, e] );
6165 - }
6166 - },
 7403+/* Handles responses to an ajax request:
 7404+ * - sets all responseXXX fields accordingly
 7405+ * - finds the right dataType (mediates between content-type and expected dataType)
 7406+ * - returns the corresponding response
 7407+ */
 7408+function ajaxHandleResponses( s, jqXHR, responses ) {
61677409
6168 - handleSuccess: function( s, xhr, status, data ) {
6169 - // If a local callback was specified, fire it and pass it the data
6170 - if ( s.success ) {
6171 - s.success.call( s.context, data, status, xhr );
 7410+ var contents = s.contents,
 7411+ dataTypes = s.dataTypes,
 7412+ responseFields = s.responseFields,
 7413+ ct,
 7414+ type,
 7415+ finalDataType,
 7416+ firstDataType;
 7417+
 7418+ // Fill responseXXX fields
 7419+ for( type in responseFields ) {
 7420+ if ( type in responses ) {
 7421+ jqXHR[ responseFields[type] ] = responses[ type ];
61727422 }
 7423+ }
61737424
6174 - // Fire the global callback
6175 - if ( s.global ) {
6176 - jQuery.triggerGlobal( s, "ajaxSuccess", [xhr, s] );
 7425+ // Remove auto dataType and get content-type in the process
 7426+ while( dataTypes[ 0 ] === "*" ) {
 7427+ dataTypes.shift();
 7428+ if ( ct === undefined ) {
 7429+ ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
61777430 }
6178 - },
 7431+ }
61797432
6180 - handleComplete: function( s, xhr, status ) {
6181 - // Process result
6182 - if ( s.complete ) {
6183 - s.complete.call( s.context, xhr, status );
 7433+ // Check if we're dealing with a known content-type
 7434+ if ( ct ) {
 7435+ for ( type in contents ) {
 7436+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
 7437+ dataTypes.unshift( type );
 7438+ break;
 7439+ }
61847440 }
 7441+ }
61857442
6186 - // The request was completed
6187 - if ( s.global ) {
6188 - jQuery.triggerGlobal( s, "ajaxComplete", [xhr, s] );
 7443+ // Check to see if we have a response for the expected dataType
 7444+ if ( dataTypes[ 0 ] in responses ) {
 7445+ finalDataType = dataTypes[ 0 ];
 7446+ } else {
 7447+ // Try convertible dataTypes
 7448+ for ( type in responses ) {
 7449+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
 7450+ finalDataType = type;
 7451+ break;
 7452+ }
 7453+ if ( !firstDataType ) {
 7454+ firstDataType = type;
 7455+ }
61897456 }
 7457+ // Or just use first one
 7458+ finalDataType = finalDataType || firstDataType;
 7459+ }
61907460
6191 - // Handle the global AJAX counter
6192 - if ( s.global && jQuery.active-- === 1 ) {
6193 - jQuery.event.trigger( "ajaxStop" );
 7461+ // If we found a dataType
 7462+ // We add the dataType to the list if needed
 7463+ // and return the corresponding response
 7464+ if ( finalDataType ) {
 7465+ if ( finalDataType !== dataTypes[ 0 ] ) {
 7466+ dataTypes.unshift( finalDataType );
61947467 }
6195 - },
6196 -
6197 - triggerGlobal: function( s, type, args ) {
6198 - (s.context && s.context.url == null ? jQuery(s.context) : jQuery.event).trigger(type, args);
6199 - },
 7468+ return responses[ finalDataType ];
 7469+ }
 7470+}
62007471
6201 - // Determines if an XMLHttpRequest was successful or not
6202 - httpSuccess: function( xhr ) {
6203 - try {
6204 - // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
6205 - return !xhr.status && location.protocol === "file:" ||
6206 - xhr.status >= 200 && xhr.status < 300 ||
6207 - xhr.status === 304 || xhr.status === 1223;
6208 - } catch(e) {}
 7472+// Chain conversions given the request and the original response
 7473+function ajaxConvert( s, response ) {
62097474
6210 - return false;
6211 - },
 7475+ // Apply the dataFilter if provided
 7476+ if ( s.dataFilter ) {
 7477+ response = s.dataFilter( response, s.dataType );
 7478+ }
62127479
6213 - // Determines if an XMLHttpRequest returns NotModified
6214 - httpNotModified: function( xhr, url ) {
6215 - var lastModified = xhr.getResponseHeader("Last-Modified"),
6216 - etag = xhr.getResponseHeader("Etag");
 7480+ var dataTypes = s.dataTypes,
 7481+ converters = {},
 7482+ i,
 7483+ key,
 7484+ length = dataTypes.length,
 7485+ tmp,
 7486+ // Current and previous dataTypes
 7487+ current = dataTypes[ 0 ],
 7488+ prev,
 7489+ // Conversion expression
 7490+ conversion,
 7491+ // Conversion function
 7492+ conv,
 7493+ // Conversion functions (transitive conversion)
 7494+ conv1,
 7495+ conv2;
62177496
6218 - if ( lastModified ) {
6219 - jQuery.lastModified[url] = lastModified;
6220 - }
 7497+ // For each dataType in the chain
 7498+ for( i = 1; i < length; i++ ) {
62217499
6222 - if ( etag ) {
6223 - jQuery.etag[url] = etag;
 7500+ // Create converters map
 7501+ // with lowercased keys
 7502+ if ( i === 1 ) {
 7503+ for( key in s.converters ) {
 7504+ if( typeof key === "string" ) {
 7505+ converters[ key.toLowerCase() ] = s.converters[ key ];
 7506+ }
 7507+ }
62247508 }
62257509
6226 - return xhr.status === 304;
6227 - },
 7510+ // Get the dataTypes
 7511+ prev = current;
 7512+ current = dataTypes[ i ];
62287513
6229 - httpData: function( xhr, type, s ) {
6230 - var ct = xhr.getResponseHeader("content-type") || "",
6231 - xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
6232 - data = xml ? xhr.responseXML : xhr.responseText;
 7514+ // If current is auto dataType, update it to prev
 7515+ if( current === "*" ) {
 7516+ current = prev;
 7517+ // If no auto and dataTypes are actually different
 7518+ } else if ( prev !== "*" && prev !== current ) {
62337519
6234 - if ( xml && data.documentElement.nodeName === "parsererror" ) {
6235 - jQuery.error( "parsererror" );
 7520+ // Get the converter
 7521+ conversion = prev + " " + current;
 7522+ conv = converters[ conversion ] || converters[ "* " + current ];
 7523+
 7524+ // If there is no direct converter, search transitively
 7525+ if ( !conv ) {
 7526+ conv2 = undefined;
 7527+ for( conv1 in converters ) {
 7528+ tmp = conv1.split( " " );
 7529+ if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
 7530+ conv2 = converters[ tmp[1] + " " + current ];
 7531+ if ( conv2 ) {
 7532+ conv1 = converters[ conv1 ];
 7533+ if ( conv1 === true ) {
 7534+ conv = conv2;
 7535+ } else if ( conv2 === true ) {
 7536+ conv = conv1;
 7537+ }
 7538+ break;
 7539+ }
 7540+ }
 7541+ }
 7542+ }
 7543+ // If we found no converter, dispatch an error
 7544+ if ( !( conv || conv2 ) ) {
 7545+ jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
 7546+ }
 7547+ // If found converter is not an equivalence
 7548+ if ( conv !== true ) {
 7549+ // Convert with 1 or 2 converters accordingly
 7550+ response = conv ? conv( response ) : conv2( conv1(response) );
 7551+ }
62367552 }
 7553+ }
 7554+ return response;
 7555+}
62377556
6238 - // Allow a pre-filtering function to sanitize the response
6239 - // s is checked to keep backwards compatibility
6240 - if ( s && s.dataFilter ) {
6241 - data = s.dataFilter( data, type );
 7557+
 7558+
 7559+
 7560+var jsc = jQuery.now(),
 7561+ jsre = /(\=)\?(&|$)|\?\?/i;
 7562+
 7563+// Default jsonp settings
 7564+jQuery.ajaxSetup({
 7565+ jsonp: "callback",
 7566+ jsonpCallback: function() {
 7567+ return jQuery.expando + "_" + ( jsc++ );
 7568+ }
 7569+});
 7570+
 7571+// Detect, normalize options and install callbacks for jsonp requests
 7572+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
 7573+
 7574+ var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
 7575+ ( typeof s.data === "string" );
 7576+
 7577+ if ( s.dataTypes[ 0 ] === "jsonp" ||
 7578+ s.jsonp !== false && ( jsre.test( s.url ) ||
 7579+ inspectData && jsre.test( s.data ) ) ) {
 7580+
 7581+ var responseContainer,
 7582+ jsonpCallback = s.jsonpCallback =
 7583+ jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
 7584+ previous = window[ jsonpCallback ],
 7585+ url = s.url,
 7586+ data = s.data,
 7587+ replace = "$1" + jsonpCallback + "$2";
 7588+
 7589+ if ( s.jsonp !== false ) {
 7590+ url = url.replace( jsre, replace );
 7591+ if ( s.url === url ) {
 7592+ if ( inspectData ) {
 7593+ data = data.replace( jsre, replace );
 7594+ }
 7595+ if ( s.data === data ) {
 7596+ // Add callback manually
 7597+ url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
 7598+ }
 7599+ }
62427600 }
62437601
6244 - // The filter can actually parse the response
6245 - if ( typeof data === "string" ) {
6246 - // Get the JavaScript object, if JSON is used.
6247 - if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
6248 - data = jQuery.parseJSON( data );
 7602+ s.url = url;
 7603+ s.data = data;
62497604
6250 - // If the type is "script", eval it in global context
6251 - } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
6252 - jQuery.globalEval( data );
 7605+ // Install callback
 7606+ window[ jsonpCallback ] = function( response ) {
 7607+ responseContainer = [ response ];
 7608+ };
 7609+
 7610+ // Clean-up function
 7611+ jqXHR.always(function() {
 7612+ // Set callback back to previous value
 7613+ window[ jsonpCallback ] = previous;
 7614+ // Call if it was a function and we have a response
 7615+ if ( responseContainer && jQuery.isFunction( previous ) ) {
 7616+ window[ jsonpCallback ]( responseContainer[ 0 ] );
62537617 }
 7618+ });
 7619+
 7620+ // Use data converter to retrieve json after script execution
 7621+ s.converters["script json"] = function() {
 7622+ if ( !responseContainer ) {
 7623+ jQuery.error( jsonpCallback + " was not called" );
 7624+ }
 7625+ return responseContainer[ 0 ];
 7626+ };
 7627+
 7628+ // force json dataType
 7629+ s.dataTypes[ 0 ] = "json";
 7630+
 7631+ // Delegate to script
 7632+ return "script";
 7633+ }
 7634+});
 7635+
 7636+
 7637+
 7638+
 7639+// Install script dataType
 7640+jQuery.ajaxSetup({
 7641+ accepts: {
 7642+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
 7643+ },
 7644+ contents: {
 7645+ script: /javascript|ecmascript/
 7646+ },
 7647+ converters: {
 7648+ "text script": function( text ) {
 7649+ jQuery.globalEval( text );
 7650+ return text;
62547651 }
 7652+ }
 7653+});
62557654
6256 - return data;
 7655+// Handle cache's special case and global
 7656+jQuery.ajaxPrefilter( "script", function( s ) {
 7657+ if ( s.cache === undefined ) {
 7658+ s.cache = false;
62577659 }
 7660+ if ( s.crossDomain ) {
 7661+ s.type = "GET";
 7662+ s.global = false;
 7663+ }
 7664+});
62587665
 7666+// Bind script tag hack transport
 7667+jQuery.ajaxTransport( "script", function(s) {
 7668+
 7669+ // This transport only deals with cross domain requests
 7670+ if ( s.crossDomain ) {
 7671+
 7672+ var script,
 7673+ head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
 7674+
 7675+ return {
 7676+
 7677+ send: function( _, callback ) {
 7678+
 7679+ script = document.createElement( "script" );
 7680+
 7681+ script.async = "async";
 7682+
 7683+ if ( s.scriptCharset ) {
 7684+ script.charset = s.scriptCharset;
 7685+ }
 7686+
 7687+ script.src = s.url;
 7688+
 7689+ // Attach handlers for all browsers
 7690+ script.onload = script.onreadystatechange = function( _, isAbort ) {
 7691+
 7692+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
 7693+
 7694+ // Handle memory leak in IE
 7695+ script.onload = script.onreadystatechange = null;
 7696+
 7697+ // Remove the script
 7698+ if ( head && script.parentNode ) {
 7699+ head.removeChild( script );
 7700+ }
 7701+
 7702+ // Dereference the script
 7703+ script = undefined;
 7704+
 7705+ // Callback if not abort
 7706+ if ( !isAbort ) {
 7707+ callback( 200, "success" );
 7708+ }
 7709+ }
 7710+ };
 7711+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
 7712+ // This arises when a base node is used (#2709 and #4378).
 7713+ head.insertBefore( script, head.firstChild );
 7714+ },
 7715+
 7716+ abort: function() {
 7717+ if ( script ) {
 7718+ script.onload( 0, 1 );
 7719+ }
 7720+ }
 7721+ };
 7722+ }
62597723 });
62607724
6261 -/*
6262 - * Create the request object; Microsoft failed to properly
6263 - * implement the XMLHttpRequest in IE7 (can't request local files),
6264 - * so we use the ActiveXObject when it is available
6265 - * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
6266 - * we need a fallback.
6267 - */
6268 -if ( window.ActiveXObject ) {
6269 - jQuery.ajaxSettings.xhr = function() {
6270 - if ( window.location.protocol !== "file:" ) {
6271 - try {
6272 - return new window.XMLHttpRequest();
6273 - } catch(xhrError) {}
 7725+
 7726+
 7727+
 7728+var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
 7729+ xhrOnUnloadAbort = window.ActiveXObject ? function() {
 7730+ // Abort all pending requests
 7731+ for ( var key in xhrCallbacks ) {
 7732+ xhrCallbacks[ key ]( 0, 1 );
62747733 }
 7734+ } : false,
 7735+ xhrId = 0,
 7736+ xhrCallbacks;
62757737
6276 - try {
6277 - return new window.ActiveXObject("Microsoft.XMLHTTP");
6278 - } catch(activeError) {}
6279 - };
 7738+// Functions to create xhrs
 7739+function createStandardXHR() {
 7740+ try {
 7741+ return new window.XMLHttpRequest();
 7742+ } catch( e ) {}
62807743 }
62817744
6282 -// Does this browser support XHR requests?
6283 -jQuery.support.ajax = !!jQuery.ajaxSettings.xhr();
 7745+function createActiveXHR() {
 7746+ try {
 7747+ return new window.ActiveXObject( "Microsoft.XMLHTTP" );
 7748+ } catch( e ) {}
 7749+}
62847750
 7751+// Create the request object
 7752+// (This is still attached to ajaxSettings for backward compatibility)
 7753+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
 7754+ /* Microsoft failed to properly
 7755+ * implement the XMLHttpRequest in IE7 (can't request local files),
 7756+ * so we use the ActiveXObject when it is available
 7757+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
 7758+ * we need a fallback.
 7759+ */
 7760+ function() {
 7761+ return !this.isLocal && createStandardXHR() || createActiveXHR();
 7762+ } :
 7763+ // For all other browsers, use the standard XMLHttpRequest object
 7764+ createStandardXHR;
62857765
 7766+// Determine support properties
 7767+(function( xhr ) {
 7768+ jQuery.extend( jQuery.support, {
 7769+ ajax: !!xhr,
 7770+ cors: !!xhr && ( "withCredentials" in xhr )
 7771+ });
 7772+})( jQuery.ajaxSettings.xhr() );
62867773
 7774+// Create transport if the browser can provide an xhr
 7775+if ( jQuery.support.ajax ) {
62877776
 7777+ jQuery.ajaxTransport(function( s ) {
 7778+ // Cross domain only allowed if supported through XMLHttpRequest
 7779+ if ( !s.crossDomain || jQuery.support.cors ) {
 7780+
 7781+ var callback;
 7782+
 7783+ return {
 7784+ send: function( headers, complete ) {
 7785+
 7786+ // Get a new xhr
 7787+ var xhr = s.xhr(),
 7788+ handle,
 7789+ i;
 7790+
 7791+ // Open the socket
 7792+ // Passing null username, generates a login popup on Opera (#2865)
 7793+ if ( s.username ) {
 7794+ xhr.open( s.type, s.url, s.async, s.username, s.password );
 7795+ } else {
 7796+ xhr.open( s.type, s.url, s.async );
 7797+ }
 7798+
 7799+ // Apply custom fields if provided
 7800+ if ( s.xhrFields ) {
 7801+ for ( i in s.xhrFields ) {
 7802+ xhr[ i ] = s.xhrFields[ i ];
 7803+ }
 7804+ }
 7805+
 7806+ // Override mime type if needed
 7807+ if ( s.mimeType && xhr.overrideMimeType ) {
 7808+ xhr.overrideMimeType( s.mimeType );
 7809+ }
 7810+
 7811+ // X-Requested-With header
 7812+ // For cross-domain requests, seeing as conditions for a preflight are
 7813+ // akin to a jigsaw puzzle, we simply never set it to be sure.
 7814+ // (it can always be set on a per-request basis or even using ajaxSetup)
 7815+ // For same-domain requests, won't change header if already provided.
 7816+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
 7817+ headers[ "X-Requested-With" ] = "XMLHttpRequest";
 7818+ }
 7819+
 7820+ // Need an extra try/catch for cross domain requests in Firefox 3
 7821+ try {
 7822+ for ( i in headers ) {
 7823+ xhr.setRequestHeader( i, headers[ i ] );
 7824+ }
 7825+ } catch( _ ) {}
 7826+
 7827+ // Do send the request
 7828+ // This may raise an exception which is actually
 7829+ // handled in jQuery.ajax (so no try/catch here)
 7830+ xhr.send( ( s.hasContent && s.data ) || null );
 7831+
 7832+ // Listener
 7833+ callback = function( _, isAbort ) {
 7834+
 7835+ var status,
 7836+ statusText,
 7837+ responseHeaders,
 7838+ responses,
 7839+ xml;
 7840+
 7841+ // Firefox throws exceptions when accessing properties
 7842+ // of an xhr when a network error occured
 7843+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
 7844+ try {
 7845+
 7846+ // Was never called and is aborted or complete
 7847+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
 7848+
 7849+ // Only called once
 7850+ callback = undefined;
 7851+
 7852+ // Do not keep as active anymore
 7853+ if ( handle ) {
 7854+ xhr.onreadystatechange = jQuery.noop;
 7855+ if ( xhrOnUnloadAbort ) {
 7856+ delete xhrCallbacks[ handle ];
 7857+ }
 7858+ }
 7859+
 7860+ // If it's an abort
 7861+ if ( isAbort ) {
 7862+ // Abort it manually if needed
 7863+ if ( xhr.readyState !== 4 ) {
 7864+ xhr.abort();
 7865+ }
 7866+ } else {
 7867+ status = xhr.status;
 7868+ responseHeaders = xhr.getAllResponseHeaders();
 7869+ responses = {};
 7870+ xml = xhr.responseXML;
 7871+
 7872+ // Construct response list
 7873+ if ( xml && xml.documentElement /* #4958 */ ) {
 7874+ responses.xml = xml;
 7875+ }
 7876+ responses.text = xhr.responseText;
 7877+
 7878+ // Firefox throws an exception when accessing
 7879+ // statusText for faulty cross-domain requests
 7880+ try {
 7881+ statusText = xhr.statusText;
 7882+ } catch( e ) {
 7883+ // We normalize with Webkit giving an empty statusText
 7884+ statusText = "";
 7885+ }
 7886+
 7887+ // Filter status for non standard behaviors
 7888+
 7889+ // If the request is local and we have data: assume a success
 7890+ // (success with no data won't get notified, that's the best we
 7891+ // can do given current implementations)
 7892+ if ( !status && s.isLocal && !s.crossDomain ) {
 7893+ status = responses.text ? 200 : 404;
 7894+ // IE - #1450: sometimes returns 1223 when it should be 204
 7895+ } else if ( status === 1223 ) {
 7896+ status = 204;
 7897+ }
 7898+ }
 7899+ }
 7900+ } catch( firefoxAccessException ) {
 7901+ if ( !isAbort ) {
 7902+ complete( -1, firefoxAccessException );
 7903+ }
 7904+ }
 7905+
 7906+ // Call complete if needed
 7907+ if ( responses ) {
 7908+ complete( status, statusText, responses, responseHeaders );
 7909+ }
 7910+ };
 7911+
 7912+ // if we're in sync mode or it's in cache
 7913+ // and has been retrieved directly (IE6 & IE7)
 7914+ // we need to manually fire the callback
 7915+ if ( !s.async || xhr.readyState === 4 ) {
 7916+ callback();
 7917+ } else {
 7918+ handle = ++xhrId;
 7919+ if ( xhrOnUnloadAbort ) {
 7920+ // Create the active xhrs callbacks list if needed
 7921+ // and attach the unload handler
 7922+ if ( !xhrCallbacks ) {
 7923+ xhrCallbacks = {};
 7924+ jQuery( window ).unload( xhrOnUnloadAbort );
 7925+ }
 7926+ // Add to list of active xhrs callbacks
 7927+ xhrCallbacks[ handle ] = callback;
 7928+ }
 7929+ xhr.onreadystatechange = callback;
 7930+ }
 7931+ },
 7932+
 7933+ abort: function() {
 7934+ if ( callback ) {
 7935+ callback(0,1);
 7936+ }
 7937+ }
 7938+ };
 7939+ }
 7940+ });
 7941+}
 7942+
 7943+
 7944+
 7945+
62887946 var elemdisplay = {},
 7947+ iframe, iframeDoc,
62897948 rfxtypes = /^(?:toggle|show|hide)$/,
6290 - rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/,
 7949+ rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
62917950 timerId,
62927951 fxAttrs = [
62937952 // height animations
@@ -6295,7 +7954,11 @@
62967955 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
62977956 // opacity animations
62987957 [ "opacity" ]
6299 - ];
 7958+ ],
 7959+ fxNow,
 7960+ requestAnimationFrame = window.webkitRequestAnimationFrame ||
 7961+ window.mozRequestAnimationFrame ||
 7962+ window.oRequestAnimationFrame;
63007963
63017964 jQuery.fn.extend({
63027965 show: function( speed, easing, callback ) {
@@ -6307,19 +7970,22 @@
63087971 } else {
63097972 for ( var i = 0, j = this.length; i < j; i++ ) {
63107973 elem = this[i];
6311 - display = elem.style.display;
63127974
6313 - // Reset the inline display of this element to learn if it is
6314 - // being hidden by cascaded rules or not
6315 - if ( !jQuery.data(elem, "olddisplay") && display === "none" ) {
6316 - display = elem.style.display = "";
6317 - }
 7975+ if ( elem.style ) {
 7976+ display = elem.style.display;
63187977
6319 - // Set elements which have been overridden with display: none
6320 - // in a stylesheet to whatever the default browser style is
6321 - // for such an element
6322 - if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
6323 - jQuery.data(elem, "olddisplay", defaultDisplay(elem.nodeName));
 7978+ // Reset the inline display of this element to learn if it is
 7979+ // being hidden by cascaded rules or not
 7980+ if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
 7981+ display = elem.style.display = "";
 7982+ }
 7983+
 7984+ // Set elements which have been overridden with display: none
 7985+ // in a stylesheet to whatever the default browser style is
 7986+ // for such an element
 7987+ if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
 7988+ jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName));
 7989+ }
63247990 }
63257991 }
63267992
@@ -6327,10 +7993,13 @@
63287994 // to avoid the constant reflow
63297995 for ( i = 0; i < j; i++ ) {
63307996 elem = this[i];
6331 - display = elem.style.display;
63327997
6333 - if ( display === "" || display === "none" ) {
6334 - elem.style.display = jQuery.data(elem, "olddisplay") || "";
 7998+ if ( elem.style ) {
 7999+ display = elem.style.display;
 8000+
 8001+ if ( display === "" || display === "none" ) {
 8002+ elem.style.display = jQuery._data(elem, "olddisplay") || "";
 8003+ }
63358004 }
63368005 }
63378006
@@ -6344,17 +8013,21 @@
63458014
63468015 } else {
63478016 for ( var i = 0, j = this.length; i < j; i++ ) {
6348 - var display = jQuery.css( this[i], "display" );
 8017+ if ( this[i].style ) {
 8018+ var display = jQuery.css( this[i], "display" );
63498019
6350 - if ( display !== "none" ) {
6351 - jQuery.data( this[i], "olddisplay", display );
 8020+ if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
 8021+ jQuery._data( this[i], "olddisplay", display );
 8022+ }
63528023 }
63538024 }
63548025
63558026 // Set the display of the elements in a second loop
63568027 // to avoid the constant reflow
63578028 for ( i = 0; i < j; i++ ) {
6358 - this[i].style.display = "none";
 8029+ if ( this[i].style ) {
 8030+ this[i].style.display = "none";
 8031+ }
63598032 }
63608033
63618034 return this;
@@ -6392,32 +8065,54 @@
63938066 var optall = jQuery.speed(speed, easing, callback);
63948067
63958068 if ( jQuery.isEmptyObject( prop ) ) {
6396 - return this.each( optall.complete );
 8069+ return this.each( optall.complete, [ false ] );
63978070 }
63988071
 8072+ // Do not change referenced properties as per-property easing will be lost
 8073+ prop = jQuery.extend( {}, prop );
 8074+
63998075 return this[ optall.queue === false ? "each" : "queue" ](function() {
64008076 // XXX 'this' does not always have a nodeName when running the
64018077 // test suite
64028078
6403 - var opt = jQuery.extend({}, optall), p,
 8079+ if ( optall.queue === false ) {
 8080+ jQuery._mark( this );
 8081+ }
 8082+
 8083+ var opt = jQuery.extend( {}, optall ),
64048084 isElement = this.nodeType === 1,
64058085 hidden = isElement && jQuery(this).is(":hidden"),
6406 - self = this;
 8086+ name, val, p,
 8087+ display, e,
 8088+ parts, start, end, unit;
64078089
 8090+ // will store per property easing and be used to determine when an animation is complete
 8091+ opt.animatedProperties = {};
 8092+
64088093 for ( p in prop ) {
6409 - var name = jQuery.camelCase( p );
64108094
 8095+ // property name normalization
 8096+ name = jQuery.camelCase( p );
64118097 if ( p !== name ) {
64128098 prop[ name ] = prop[ p ];
64138099 delete prop[ p ];
6414 - p = name;
64158100 }
64168101
6417 - if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
6418 - return opt.complete.call(this);
 8102+ val = prop[ name ];
 8103+
 8104+ // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
 8105+ if ( jQuery.isArray( val ) ) {
 8106+ opt.animatedProperties[ name ] = val[ 1 ];
 8107+ val = prop[ name ] = val[ 0 ];
 8108+ } else {
 8109+ opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
64198110 }
64208111
6421 - if ( isElement && ( p === "height" || p === "width" ) ) {
 8112+ if ( val === "hide" && hidden || val === "show" && !hidden ) {
 8113+ return opt.complete.call( this );
 8114+ }
 8115+
 8116+ if ( isElement && ( name === "height" || name === "width" ) ) {
64228117 // Make sure that nothing sneaks out
64238118 // Record all 3 overflow attributes because IE does not
64248119 // change the overflow attribute when overflowX and
@@ -6433,7 +8128,7 @@
64348129 this.style.display = "inline-block";
64358130
64368131 } else {
6437 - var display = defaultDisplay(this.nodeName);
 8132+ display = defaultDisplay( this.nodeName );
64388133
64398134 // inline-level elements accept inline-block;
64408135 // block-level elements need to be inline with layout
@@ -6447,44 +8142,37 @@
64488143 }
64498144 }
64508145 }
6451 -
6452 - if ( jQuery.isArray( prop[p] ) ) {
6453 - // Create (if needed) and add to specialEasing
6454 - (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
6455 - prop[p] = prop[p][0];
6456 - }
64578146 }
64588147
64598148 if ( opt.overflow != null ) {
64608149 this.style.overflow = "hidden";
64618150 }
64628151
6463 - opt.curAnim = jQuery.extend({}, prop);
 8152+ for ( p in prop ) {
 8153+ e = new jQuery.fx( this, opt, p );
 8154+ val = prop[ p ];
64648155
6465 - jQuery.each( prop, function( name, val ) {
6466 - var e = new jQuery.fx( self, opt, name );
6467 -
64688156 if ( rfxtypes.test(val) ) {
6469 - e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
 8157+ e[ val === "toggle" ? hidden ? "show" : "hide" : val ]();
64708158
64718159 } else {
6472 - var parts = rfxnum.exec(val),
6473 - start = e.cur() || 0;
 8160+ parts = rfxnum.exec( val );
 8161+ start = e.cur();
64748162
64758163 if ( parts ) {
6476 - var end = parseFloat( parts[2] ),
6477 - unit = parts[3] || "px";
 8164+ end = parseFloat( parts[2] );
 8165+ unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
64788166
64798167 // We need to compute starting value
64808168 if ( unit !== "px" ) {
6481 - jQuery.style( self, name, (end || 1) + unit);
 8169+ jQuery.style( this, p, (end || 1) + unit);
64828170 start = ((end || 1) / e.cur()) * start;
6483 - jQuery.style( self, name, start + unit);
 8171+ jQuery.style( this, p, start + unit);
64848172 }
64858173
64868174 // If a +=/-= token was provided, we're doing a relative animation
64878175 if ( parts[1] ) {
6488 - end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
 8176+ end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
64898177 }
64908178
64918179 e.custom( start, end, unit );
@@ -6493,7 +8181,7 @@
64948182 e.custom( start, val, "" );
64958183 }
64968184 }
6497 - });
 8185+ }
64988186
64998187 // For JS strict compliance
65008188 return true;
@@ -6501,15 +8189,18 @@
65028190 },
65038191
65048192 stop: function( clearQueue, gotoEnd ) {
6505 - var timers = jQuery.timers;
6506 -
65078193 if ( clearQueue ) {
65088194 this.queue([]);
65098195 }
65108196
65118197 this.each(function() {
6512 - // go in reverse order so anything added to the queue during the loop is ignored
6513 - for ( var i = timers.length - 1; i >= 0; i-- ) {
 8198+ var timers = jQuery.timers,
 8199+ i = timers.length;
 8200+ // clear marker counters if we know they won't be
 8201+ if ( !gotoEnd ) {
 8202+ jQuery._unmark( true, this );
 8203+ }
 8204+ while ( i-- ) {
65148205 if ( timers[i].elem === this ) {
65158206 if (gotoEnd) {
65168207 // force the next step to be the last
@@ -6531,6 +8222,17 @@
65328223
65338224 });
65348225
 8226+// Animations created synchronously will run synchronously
 8227+function createFxNow() {
 8228+ setTimeout( clearFxNow, 0 );
 8229+ return ( fxNow = jQuery.now() );
 8230+}
 8231+
 8232+function clearFxNow() {
 8233+ fxNow = undefined;
 8234+}
 8235+
 8236+// Generate parameters to create a standard animation
65358237 function genFx( type, num ) {
65368238 var obj = {};
65378239
@@ -6569,10 +8271,13 @@
65708272
65718273 // Queueing
65728274 opt.old = opt.complete;
6573 - opt.complete = function() {
 8275+ opt.complete = function( noUnmark ) {
65748276 if ( opt.queue !== false ) {
6575 - jQuery(this).dequeue();
 8277+ jQuery.dequeue( this );
 8278+ } else if ( noUnmark !== false ) {
 8279+ jQuery._unmark( this );
65768280 }
 8281+
65778282 if ( jQuery.isFunction( opt.old ) ) {
65788283 opt.old.call( this );
65798284 }
@@ -6597,9 +8302,7 @@
65988303 this.elem = elem;
65998304 this.prop = prop;
66008305
6601 - if ( !options.orig ) {
6602 - options.orig = {};
6603 - }
 8306+ options.orig = options.orig || {};
66048307 }
66058308
66068309 });
@@ -6620,19 +8323,24 @@
66218324 return this.elem[ this.prop ];
66228325 }
66238326
6624 - var r = parseFloat( jQuery.css( this.elem, this.prop ) );
6625 - return r && r > -10000 ? r : 0;
 8327+ var parsed,
 8328+ r = jQuery.css( this.elem, this.prop );
 8329+ // Empty strings, null, undefined and "auto" are converted to 0,
 8330+ // complex values such as "rotate(1rad)" are returned as is,
 8331+ // simple values such as "10px" are parsed to Float.
 8332+ return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
66268333 },
66278334
66288335 // Start an animation from one number to another
66298336 custom: function( from, to, unit ) {
66308337 var self = this,
6631 - fx = jQuery.fx;
 8338+ fx = jQuery.fx,
 8339+ raf;
66328340
6633 - this.startTime = jQuery.now();
 8341+ this.startTime = fxNow || createFxNow();
66348342 this.start = from;
66358343 this.end = to;
6636 - this.unit = unit || this.unit || "px";
 8344+ this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
66378345 this.now = this.start;
66388346 this.pos = this.state = 0;
66398347
@@ -6643,7 +8351,20 @@
66448352 t.elem = this.elem;
66458353
66468354 if ( t() && jQuery.timers.push(t) && !timerId ) {
6647 - timerId = setInterval(fx.tick, fx.interval);
 8355+ // Use requestAnimationFrame instead of setInterval if available
 8356+ if ( requestAnimationFrame ) {
 8357+ timerId = 1;
 8358+ raf = function() {
 8359+ // When timerId gets set to null at any point, this stops
 8360+ if ( timerId ) {
 8361+ requestAnimationFrame( raf );
 8362+ fx.tick();
 8363+ }
 8364+ };
 8365+ requestAnimationFrame( raf );
 8366+ } else {
 8367+ timerId = setInterval( fx.tick, fx.interval );
 8368+ }
66488369 }
66498370 },
66508371
@@ -6674,60 +8395,64 @@
66758396
66768397 // Each step of an animation
66778398 step: function( gotoEnd ) {
6678 - var t = jQuery.now(), done = true;
 8399+ var t = fxNow || createFxNow(),
 8400+ done = true,
 8401+ elem = this.elem,
 8402+ options = this.options,
 8403+ i, n;
66798404
6680 - if ( gotoEnd || t >= this.options.duration + this.startTime ) {
 8405+ if ( gotoEnd || t >= options.duration + this.startTime ) {
66818406 this.now = this.end;
66828407 this.pos = this.state = 1;
66838408 this.update();
66848409
6685 - this.options.curAnim[ this.prop ] = true;
 8410+ options.animatedProperties[ this.prop ] = true;
66868411
6687 - for ( var i in this.options.curAnim ) {
6688 - if ( this.options.curAnim[i] !== true ) {
 8412+ for ( i in options.animatedProperties ) {
 8413+ if ( options.animatedProperties[i] !== true ) {
66898414 done = false;
66908415 }
66918416 }
66928417
66938418 if ( done ) {
66948419 // Reset the overflow
6695 - if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
6696 - var elem = this.elem,
6697 - options = this.options;
 8420+ if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
66988421
66998422 jQuery.each( [ "", "X", "Y" ], function (index, value) {
67008423 elem.style[ "overflow" + value ] = options.overflow[index];
6701 - } );
 8424+ });
67028425 }
67038426
67048427 // Hide the element if the "hide" operation was done
6705 - if ( this.options.hide ) {
6706 - jQuery(this.elem).hide();
 8428+ if ( options.hide ) {
 8429+ jQuery(elem).hide();
67078430 }
67088431
67098432 // Reset the properties, if the item has been hidden or shown
6710 - if ( this.options.hide || this.options.show ) {
6711 - for ( var p in this.options.curAnim ) {
6712 - jQuery.style( this.elem, p, this.options.orig[p] );
 8433+ if ( options.hide || options.show ) {
 8434+ for ( var p in options.animatedProperties ) {
 8435+ jQuery.style( elem, p, options.orig[p] );
67138436 }
67148437 }
67158438
67168439 // Execute the complete function
6717 - this.options.complete.call( this.elem );
 8440+ options.complete.call( elem );
67188441 }
67198442
67208443 return false;
67218444
67228445 } else {
6723 - var n = t - this.startTime;
6724 - this.state = n / this.options.duration;
 8446+ // classical easing cannot be used with an Infinity duration
 8447+ if ( options.duration == Infinity ) {
 8448+ this.now = t;
 8449+ } else {
 8450+ n = t - this.startTime;
 8451+ this.state = n / options.duration;
67258452
6726 - // Perform the easing function, defaults to swing
6727 - var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
6728 - var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
6729 - this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
6730 - this.now = this.start + ((this.end - this.start) * this.pos);
6731 -
 8453+ // Perform the easing function, defaults to swing
 8454+ this.pos = jQuery.easing[ options.animatedProperties[ this.prop ] ]( this.state, n, 0, 1, options.duration );
 8455+ this.now = this.start + ((this.end - this.start) * this.pos);
 8456+ }
67328457 // Perform the next step of the animation
67338458 this.update();
67348459 }
@@ -6738,9 +8463,7 @@
67398464
67408465 jQuery.extend( jQuery.fx, {
67418466 tick: function() {
6742 - var timers = jQuery.timers;
6743 -
6744 - for ( var i = 0; i < timers.length; i++ ) {
 8467+ for ( var timers = jQuery.timers, i = 0 ; i < timers.length ; ++i ) {
67458468 if ( !timers[i]() ) {
67468469 timers.splice(i--, 1);
67478470 }
@@ -6788,17 +8511,45 @@
67898512 };
67908513 }
67918514
 8515+// Try to restore the default display value of an element
67928516 function defaultDisplay( nodeName ) {
 8517+
67938518 if ( !elemdisplay[ nodeName ] ) {
6794 - var elem = jQuery("<" + nodeName + ">").appendTo("body"),
6795 - display = elem.css("display");
67968519
 8520+ var elem = jQuery( "<" + nodeName + ">" ).appendTo( "body" ),
 8521+ display = elem.css( "display" );
 8522+
67978523 elem.remove();
67988524
 8525+ // If the simple way fails,
 8526+ // get element's real default display by attaching it to a temp iframe
67998527 if ( display === "none" || display === "" ) {
6800 - display = "block";
 8528+ // No iframe to use yet, so create it
 8529+ if ( !iframe ) {
 8530+ iframe = document.createElement( "iframe" );
 8531+ iframe.frameBorder = iframe.width = iframe.height = 0;
 8532+ }
 8533+
 8534+ document.body.appendChild( iframe );
 8535+
 8536+ // Create a cacheable copy of the iframe document on first call.
 8537+ // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake html
 8538+ // document to it, Webkit & Firefox won't allow reusing the iframe document
 8539+ if ( !iframeDoc || !iframe.createElement ) {
 8540+ iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
 8541+ iframeDoc.write( "<!doctype><html><body></body></html>" );
 8542+ }
 8543+
 8544+ elem = iframeDoc.createElement( nodeName );
 8545+
 8546+ iframeDoc.body.appendChild( elem );
 8547+
 8548+ display = jQuery.css( elem, "display" );
 8549+
 8550+ document.body.removeChild( iframe );
68018551 }
68028552
 8553+ // Store the correct default display
68038554 elemdisplay[ nodeName ] = display;
68048555 }
68058556
@@ -6815,7 +8566,7 @@
68168567 jQuery.fn.offset = function( options ) {
68178568 var elem = this[0], box;
68188569
6819 - if ( options ) {
 8570+ if ( options ) {
68208571 return this.each(function( i ) {
68218572 jQuery.offset.setOffset( this, options, i );
68228573 });
@@ -6838,15 +8589,15 @@
68398590
68408591 // Make sure we're not dealing with a disconnected DOM node
68418592 if ( !box || !jQuery.contains( docElem, elem ) ) {
6842 - return box || { top: 0, left: 0 };
 8593+ return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
68438594 }
68448595
68458596 var body = doc.body,
68468597 win = getWindow(doc),
68478598 clientTop = docElem.clientTop || body.clientTop || 0,
68488599 clientLeft = docElem.clientLeft || body.clientLeft || 0,
6849 - scrollTop = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ),
6850 - scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft),
 8600+ scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop,
 8601+ scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
68518602 top = box.top + scrollTop - clientTop,
68528603 left = box.left + scrollLeft - clientLeft;
68538604
@@ -6857,7 +8608,7 @@
68588609 jQuery.fn.offset = function( options ) {
68598610 var elem = this[0];
68608611
6861 - if ( options ) {
 8612+ if ( options ) {
68628613 return this.each(function( i ) {
68638614 jQuery.offset.setOffset( this, options, i );
68648615 });
@@ -6959,7 +8710,6 @@
69608711 this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
69618712
69628713 body.removeChild( container );
6963 - body = container = innerDiv = checkDiv = table = td = null;
69648714 jQuery.offset.initialize = jQuery.noop;
69658715 },
69668716
@@ -6976,7 +8726,7 @@
69778727
69788728 return { top: top, left: left };
69798729 },
6980 -
 8730+
69818731 setOffset: function( elem, options, i ) {
69828732 var position = jQuery.css( elem, "position" );
69838733
@@ -6989,17 +8739,19 @@
69908740 curOffset = curElem.offset(),
69918741 curCSSTop = jQuery.css( elem, "top" ),
69928742 curCSSLeft = jQuery.css( elem, "left" ),
6993 - calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1),
 8743+ calculatePosition = (position === "absolute" || position === "fixed") && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
69948744 props = {}, curPosition = {}, curTop, curLeft;
69958745
6996 - // need to be able to calculate position if either top or left is auto and position is absolute
 8746+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
69978747 if ( calculatePosition ) {
69988748 curPosition = curElem.position();
 8749+ curTop = curPosition.top;
 8750+ curLeft = curPosition.left;
 8751+ } else {
 8752+ curTop = parseFloat( curCSSTop ) || 0;
 8753+ curLeft = parseFloat( curCSSLeft ) || 0;
69998754 }
70008755
7001 - curTop = calculatePosition ? curPosition.top : parseInt( curCSSTop, 10 ) || 0;
7002 - curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0;
7003 -
70048756 if ( jQuery.isFunction( options ) ) {
70058757 options = options.call( elem, i, curOffset );
70068758 }
@@ -7010,7 +8762,7 @@
70118763 if (options.left != null) {
70128764 props.left = (options.left - curOffset.left) + curLeft;
70138765 }
7014 -
 8766+
70158767 if ( "using" in options ) {
70168768 options.using.call( elem, props );
70178769 } else {
@@ -7068,29 +8820,16 @@
70698821 jQuery.each( ["Left", "Top"], function( i, name ) {
70708822 var method = "scroll" + name;
70718823
7072 - jQuery.fn[ method ] = function(val) {
7073 - var elem = this[0], win;
7074 -
7075 - if ( !elem ) {
7076 - return null;
7077 - }
 8824+ jQuery.fn[ method ] = function( val ) {
 8825+ var elem, win;
70788826
7079 - if ( val !== undefined ) {
7080 - // Set the scroll offset
7081 - return this.each(function() {
7082 - win = getWindow( this );
 8827+ if ( val === undefined ) {
 8828+ elem = this[ 0 ];
70838829
7084 - if ( win ) {
7085 - win.scrollTo(
7086 - !i ? val : jQuery(win).scrollLeft(),
7087 - i ? val : jQuery(win).scrollTop()
7088 - );
 8830+ if ( !elem ) {
 8831+ return null;
 8832+ }
70898833
7090 - } else {
7091 - this[ method ] = val;
7092 - }
7093 - });
7094 - } else {
70958834 win = getWindow( elem );
70968835
70978836 // Return the scroll offset
@@ -7099,6 +8838,21 @@
71008839 win.document.body[ method ] :
71018840 elem[ method ];
71028841 }
 8842+
 8843+ // Set the scroll offset
 8844+ return this.each(function() {
 8845+ win = getWindow( this );
 8846+
 8847+ if ( win ) {
 8848+ win.scrollTo(
 8849+ !i ? val : jQuery( win ).scrollLeft(),
 8850+ i ? val : jQuery( win ).scrollTop()
 8851+ );
 8852+
 8853+ } else {
 8854+ this[ method ] = val;
 8855+ }
 8856+ });
71038857 };
71048858 });
71058859
@@ -7138,7 +8892,7 @@
71398893 if ( !elem ) {
71408894 return size == null ? null : this;
71418895 }
7142 -
 8896+
71438897 if ( jQuery.isFunction( size ) ) {
71448898 return this.each(function( i ) {
71458899 var self = jQuery( this );
@@ -7148,8 +8902,10 @@
71498903
71508904 if ( jQuery.isWindow( elem ) ) {
71518905 // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
7152 - return elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
7153 - elem.document.body[ "client" + name ];
 8906+ // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
 8907+ var docElemProp = elem.document.documentElement[ "client" + name ];
 8908+ return elem.document.compatMode === "CSS1Compat" && docElemProp ||
 8909+ elem.document.body[ "client" + name ] || docElemProp;
71548910
71558911 // Get document width or height
71568912 } else if ( elem.nodeType === 9 ) {
@@ -7176,4 +8932,5 @@
71778933 });
71788934
71798935
 8936+window.jQuery = window.$ = jQuery;
71808937 })(window);

Follow-up revisions

RevisionCommit summaryAuthorDate
r89865Follow-up r89853: Documentation for completenesstest + minor fixes/whitespacekrinkle00:24, 11 June 2011
r89866Upgrade jQuery from 1.4.4 to 1.6.1...krinkle00:25, 11 June 2011
r91845Update jQuery from 1.6.1 to 1.6.2 (maintenance/bugfix release)...krinkle21:17, 10 July 2011
r92349MFT to REL1_18...hashar09:11, 16 July 2011
r94636Followup r89853, tweaks for jquery.qunit.completenessTest:...catrope13:33, 16 August 2011

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r89845Review of unit test suites...krinkle19:55, 10 June 2011

Comments

#Comment by Krinkle (talk | contribs)   00:29, 11 June 2011

jQuery was updated, was intended for r89866 (1 minute after). Sorry for the mixup.

#Comment by Reedy (talk | contribs)   00:27, 12 July 2011

Tagging 1.18, but only jQuery to be merged

#Comment by Hashar (talk | contribs)   09:11, 16 July 2011

jQuery part merged in 1.18 with r92349

#Comment by Catrope (talk | contribs)   13:33, 16 August 2011
+		console.log( 'CompletenessTest.ACTION_CHECK', that );

So this code assumes console.log() will be callable? Doesn't that cause JS errors on browsers where it's not present?

Status & tagging log