你的位置:首页 > Java教程

[Java教程]立即执行函数(IIFE)的理解与运用


作为JavaScript的常用语法,立即执行函数IIFE(Immediately-Invoked Function Expression)是值得我们认真去学习探究的。

 

一、创建函数的两种方式

我们先从基础讲起,要创建一个JS函数,有两种方式。

 

(一)函数定义(Function Declaration)

function Identifier ( Parameters ){ FunctionBody }

函数定义中,参数(Parameters)标识符(Identifier )是必不可少的。如果遗漏,会报提示如下错误:Expected identifier

 

(二)函数表达式(Function Expression)

function Identifier(Parameters){ FunctionBody }

函数表达式中,参数和标识符都是可选的。

那么我们是不是可以通过有无标识符来判断,创建函数的是一个函数定义,还是一个函数表达式呢?很遗憾,不行!

我们刚刚说过,函数表达式中标识符是可选的。那如果函数表达式有标识符,又该如何判断?

其实,"function Identifier(Parameters){ FunctionBody }"并不是一个完整的函数表达式,完整的函数的表达式,需要一个赋值操作。

比如: var name=function Identifier(Parameters){ FunctionBody }

这里的Identifier常常被省略,至于为什么,由于该主题内容涉及面较广,在此文中不作讨论。

好了。两种创建函数的方式实例如下:

//function expressionvar myExpression = function () { return window.location }//function declarationfunction myDeclaration() { return window.location.hostname }

 

二、立即执行函数

顾名思义,立即执行函数可以让你的函数在创建后立即执行。

(一)基本结构

这样的函数有多常用呢,我们可以看看下面的代码:

(function( window, undefined ) {//……})(window);

这段代码,大家一定不会陌生。是的,它就是我们"Write less, do more"的jQuery。

jQuery整个文件就是一个立即执行函数。

(function(){})();  是立即执行函数常用的表现形式之一。

另一种也很常用:

(function(){}());

以上两种是比较常用的写法,但立即执行函数的写法因人而异。记住以下两点就可以了。

如果是函数表达式,可直接在其后加"()"立即执行。

如果是函数声明,可以通过"()"、"+"、"-"、"void"、"new"等运算符将其转换为函数表达式,然后再加"()"立即执行。

比如,下面的写法也是没有问题的。

void function(){}(alert("ok"));

在执行前,可以在最后调用的"()"传入我们需要的参数,比如jQuery就把window对象作为实参传入了立即函数内部。

(二)使用时机

什么时候需要用到立即执行函数呢?

1.当我们需要写一个js文件,并且复用率很高的时候,建议使用。

2.如果声明的函数只需要调用一次,建议使用。

3.独立模块,这个和第一点差不多。单独提出来,是想强调一下立即执行函数的好处,开发时,它能做到各模块的低耦合,减少对全局作用域的污染。

(三)实例及好处

无实例,无真相。找什么实例好呢?还是我们的jQuery吧。

  1 /*!  2  * jQuery JavaScript Library v1.4.4  3  * http://jquery.com/  4  *  5  * Copyright 2010, John Resig  6  * Dual licensed under the MIT or GPL Version 2 licenses.  7  * http://jquery.org/license  8  *  9  * Includes Sizzle.js 10  * http://sizzlejs.com/ 11  * Copyright 2010, The Dojo Foundation 12  * Released under the MIT, BSD, and GPL Licenses. 13  * 14  * Date: Thu Nov 11 19:04:53 2010 -0500 15 */ 16 (function( window, undefined ) { 17  18 // Use the correct document accordingly with window argument (sandbox) 19 var document = window.document; 20 var jQuery = (function() { 21  22 // Define a local copy of jQuery 23 var jQuery = function( selector, context ) { 24     // The jQuery object is actually just the init constructor 'enhanced' 25     return new jQuery.fn.init( selector, context ); 26   }, 27  28   // Map over jQuery in case of overwrite 29   _jQuery = window.jQuery, 30  31   // Map over the $ in case of overwrite 32   _$ = window.$, 33  34   // A central reference to the root jQuery(document) 35   rootjQuery, 36  37   // A simple way to check for HTML strings or ID strings 38   // (both of which we optimize for) 39   quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, 40  41   // Is it a simple selector 42   isSimple = /^.[^:#\[\.,]*$/, 43  44   // Check if a string has a non-whitespace character in it 45   rnotwhite = /\S/, 46   rwhite = /\s/, 47  48   // Used for trimming whitespace 49   trimLeft = /^\s+/, 50   trimRight = /\s+$/, 51  52   // Check for non-word characters 53   rnonword = /\W/, 54  55   // Check for digits 56   rdigit = /\d/, 57  58   // Match a standalone tag 59   rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, 60  61   // JSON RegExp 62   rvalidchars = /^[\],:{}\s]*$/, 63   rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, 64   rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, 65   rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, 66  67   // Useragent RegExp 68   rwebkit = /(webkit)[ \/]([\w.]+)/, 69   ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, 70   rmsie = /(msie) ([\w.]+)/, 71   rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, 72  73   // Keep a UserAgent string for use with jQuery.browser 74   userAgent = navigator.userAgent, 75  76   // For matching the engine and version of the browser 77   browserMatch, 78    79   // Has the ready events already been bound? 80   readyBound = false, 81    82   // The functions to execute on DOM ready 83   readyList = [], 84  85   // The ready event handler 86   DOMContentLoaded, 87  88   // Save a reference to some core methods 89   toString = Object.prototype.toString, 90   hasOwn = Object.prototype.hasOwnProperty, 91   push = Array.prototype.push, 92   slice = Array.prototype.slice, 93   trim = String.prototype.trim, 94   indexOf = Array.prototype.indexOf, 95    96   // [[Class]] -> type pairs 97   class2type = {}; 98  99 jQuery.fn = jQuery.prototype = { 100   init: function( selector, context ) { 101     var match, elem, ret, doc; 102  103     // Handle $(""), $(null), or $(undefined) 104     if ( !selector ) { 105       return this; 106     } 107  108     // Handle $(DOMElement) 109     if ( selector.nodeType ) { 110       this.context = this[0] = selector; 111       this.length = 1; 112       return this; 113     } 114      115     // The body element only exists once, optimize finding it 116     if ( selector === "body" && !context && document.body ) { 117       this.context = document; 118       this[0] = document.body; 119       this.selector = "body"; 120       this.length = 1; 121       return this; 122     } 123  124     // Handle HTML strings 125     if ( typeof selector === "string" ) { 126       // Are we dealing with HTML string or an ID? 127       match = quickExpr.exec( selector ); 128  129       // Verify a match, and that no context was specified for #id 130       if ( match && (match[1] || !context) ) { 131  132         // HANDLE: $(html) -> $(array) 133         if ( match[1] ) { 134           doc = (context ? context.ownerDocument || context : document); 135  136           // If a single string is passed in and it's a single tag 137           // just do a createElement and skip the rest 138           ret = rsingleTag.exec( selector ); 139  140           if ( ret ) { 141             if ( jQuery.isPlainObject( context ) ) { 142               selector = [ document.createElement( ret[1] ) ]; 143               jQuery.fn.attr.call( selector, context, true ); 144  145             } else { 146               selector = [ doc.createElement( ret[1] ) ]; 147             } 148  149           } else { 150             ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); 151             selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; 152           } 153            154           return jQuery.merge( this, selector ); 155            156         // HANDLE: $("#id") 157         } else { 158           elem = document.getElementById( match[2] ); 159  160           // Check parentNode to catch when Blackberry 4.6 returns 161           // nodes that are no longer in the document #6963 162           if ( elem && elem.parentNode ) { 163             // Handle the case where IE and Opera return items 164             // by name instead of ID 165             if ( elem.id !== match[2] ) { 166               return rootjQuery.find( selector ); 167             } 168  169             // Otherwise, we inject the element directly into the jQuery object 170             this.length = 1; 171             this[0] = elem; 172           } 173  174           this.context = document; 175           this.selector = selector; 176           return this; 177         } 178  179       // HANDLE: $("TAG") 180       } else if ( !context && !rnonword.test( selector ) ) { 181         this.selector = selector; 182         this.context = document; 183         selector = document.getElementsByTagName( selector ); 184         return jQuery.merge( this, selector ); 185  186       // HANDLE: $(expr, $(...)) 187       } else if ( !context || context.jquery ) { 188         return (context || rootjQuery).find( selector ); 189  190       // HANDLE: $(expr, context) 191       // (which is just equivalent to: $(context).find(expr) 192       } else { 193         return jQuery( context ).find( selector ); 194       } 195  196     // HANDLE: $(function) 197     // Shortcut for document ready 198     } else if ( jQuery.isFunction( selector ) ) { 199       return rootjQuery.ready( selector ); 200     } 201  202     if (selector.selector !== undefined) { 203       this.selector = selector.selector; 204       this.context = selector.context; 205     } 206  207     return jQuery.makeArray( selector, this ); 208   }, 209  210   // Start with an empty selector 211   selector: "", 212  213   // The current version of jQuery being used 214   jquery: "1.4.4", 215  216   // The default length of a jQuery object is 0 217   length: 0, 218  219   // The number of elements contained in the matched element set 220   size: function() { 221     return this.length; 222   }, 223  224   toArray: function() { 225     return slice.call( this, 0 ); 226   }, 227  228   // Get the Nth element in the matched element set OR 229   // Get the whole matched element set as a clean array 230   get: function( num ) { 231     return num == null ? 232  233       // Return a 'clean' array 234       this.toArray() : 235  236       // Return just the object 237       ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); 238   }, 239  240   // Take an array of elements and push it onto the stack 241   // (returning the new matched element set) 242   pushStack: function( elems, name, selector ) { 243     // Build a new jQuery matched element set 244     var ret = jQuery(); 245  246     if ( jQuery.isArray( elems ) ) { 247       push.apply( ret, elems ); 248      249     } else { 250       jQuery.merge( ret, elems ); 251     } 252  253     // Add the old object onto the stack (as a reference) 254     ret.prevObject = this; 255  256     ret.context = this.context; 257  258     if ( name === "find" ) { 259       ret.selector = this.selector + (this.selector ? " " : "") + selector; 260     } else if ( name ) { 261       ret.selector = this.selector + "." + name + "(" + selector + ")"; 262     } 263  264     // Return the newly-formed element set 265     return ret; 266   }, 267  268   // Execute a callback for every element in the matched set. 269   // (You can seed the arguments with an array of args, but this is 270   // only used internally.) 271   each: function( callback, args ) { 272     return jQuery.each( this, callback, args ); 273   }, 274    275   ready: function( fn ) { 276     // Attach the listeners 277     jQuery.bindReady(); 278  279     // If the DOM is already ready 280     if ( jQuery.isReady ) { 281       // Execute the function immediately 282       fn.call( document, jQuery ); 283  284     // Otherwise, remember the function for later 285     } else if ( readyList ) { 286       // Add the function to the wait list 287       readyList.push( fn ); 288     } 289  290     return this; 291   }, 292    293   eq: function( i ) { 294     return i === -1 ? 295       this.slice( i ) : 296       this.slice( i, +i + 1 ); 297   }, 298  299   first: function() { 300     return this.eq( 0 ); 301   }, 302  303   last: function() { 304     return this.eq( -1 ); 305   }, 306  307   slice: function() { 308     return this.pushStack( slice.apply( this, arguments ), 309       "slice", slice.call(arguments).join(",") ); 310   }, 311  312   map: function( callback ) { 313     return this.pushStack( jQuery.map(this, function( elem, i ) { 314       return callback.call( elem, i, elem ); 315     })); 316   }, 317    318   end: function() { 319     return this.prevObject || jQuery(null); 320   }, 321  322   // For internal use only. 323   // Behaves like an Array's method, not like a jQuery method. 324   push: push, 325   sort: [].sort, 326   splice: [].splice 327 }; 328  329 // Give the init function the jQuery prototype for later instantiation 330 jQuery.fn.init.prototype = jQuery.fn; 331  332 jQuery.extend = jQuery.fn.extend = function() { 333   var options, name, src, copy, copyIsArray, clone, 334     target = arguments[0] || {}, 335     i = 1, 336     length = arguments.length, 337     deep = false; 338  339   // Handle a deep copy situation 340   if ( typeof target === "boolean" ) { 341     deep = target; 342     target = arguments[1] || {}; 343     // skip the boolean and the target 344     i = 2; 345   } 346  347   // Handle case when target is a string or something (possible in deep copy) 348   if ( typeof target !== "object" && !jQuery.isFunction(target) ) { 349     target = {}; 350   } 351  352   // extend jQuery itself if only one argument is passed 353   if ( length === i ) { 354     target = this; 355     --i; 356   } 357  358   for ( ; i < length; i++ ) { 359     // Only deal with non-null/undefined values 360     if ( (options = arguments[ i ]) != null ) { 361       // Extend the base object 362       for ( name in options ) { 363         src = target[ name ]; 364         copy = options[ name ]; 365  366         // Prevent never-ending loop 367         if ( target === copy ) { 368           continue; 369         } 370  371         // Recurse if we're merging plain objects or arrays 372         if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { 373           if ( copyIsArray ) { 374             copyIsArray = false; 375             clone = src && jQuery.isArray(src) ? src : []; 376  377           } else { 378             clone = src && jQuery.isPlainObject(src) ? src : {}; 379           } 380  381           // Never move original objects, clone them 382           target[ name ] = jQuery.extend( deep, clone, copy ); 383  384         // Don't bring in undefined values 385         } else if ( copy !== undefined ) { 386           target[ name ] = copy; 387         } 388       } 389     } 390   } 391  392   // Return the modified object 393   return target; 394 }; 395  396 jQuery.extend({ 397   noConflict: function( deep ) { 398     window.$ = _$; 399  400     if ( deep ) { 401       window.jQuery = _jQuery; 402     } 403  404     return jQuery; 405   }, 406    407   // Is the DOM ready to be used? Set to true once it occurs. 408   isReady: false, 409  410   // A counter to track how many items to wait for before 411   // the ready event fires. See #6781 412   readyWait: 1, 413    414   // Handle when the DOM is ready 415   ready: function( wait ) { 416     // A third-party is pushing the ready event forwards 417     if ( wait === true ) { 418       jQuery.readyWait--; 419     } 420  421     // Make sure that the DOM is not already loaded 422     if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { 423       // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). 424       if ( !document.body ) { 425         return setTimeout( jQuery.ready, 1 ); 426       } 427  428       // Remember that the DOM is ready 429       jQuery.isReady = true; 430  431       // If a normal DOM Ready event fired, decrement, and wait if need be 432       if ( wait !== true && --jQuery.readyWait > 0 ) { 433         return; 434       } 435  436       // If there are functions bound, to execute 437       if ( readyList ) { 438         // Execute all of them 439         var fn, 440           i = 0, 441           ready = readyList; 442  443         // Reset the list of functions 444         readyList = null; 445  446         while ( (fn = ready[ i++ ]) ) { 447           fn.call( document, jQuery ); 448         } 449  450         // Trigger any bound ready events 451         if ( jQuery.fn.trigger ) { 452           jQuery( document ).trigger( "ready" ).unbind( "ready" ); 453         } 454       } 455     } 456   }, 457    458   bindReady: function() { 459     if ( readyBound ) { 460       return; 461     } 462  463     readyBound = true; 464  465     // Catch cases where $(document).ready() is called after the 466     // browser event has already occurred. 467     if ( document.readyState === "complete" ) { 468       // Handle it asynchronously to allow scripts the opportunity to delay ready 469       return setTimeout( jQuery.ready, 1 ); 470     } 471  472     // Mozilla, Opera and webkit nightlies currently support this event 473     if ( document.addEventListener ) { 474       // Use the handy event callback 475       document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); 476        477       // A fallback to window.onload, that will always work 478       window.addEventListener( "load", jQuery.ready, false ); 479  480     // If IE event model is used 481     } else if ( document.attachEvent ) { 482       // ensure firing before onload, 483       // maybe late but safe also for iframes 484       document.attachEvent("onreadystatechange", DOMContentLoaded); 485        486       // A fallback to window.onload, that will always work 487       window.attachEvent( "onload", jQuery.ready ); 488  489       // If IE and not a frame 490       // continually check to see if the document is ready 491       var toplevel = false; 492  493       try { 494         toplevel = window.frameElement == null; 495       } catch(e) {} 496  497       if ( document.documentElement.doScroll && toplevel ) { 498         doScrollCheck(); 499       } 500     } 501   }, 502  503   // See test/unit/core.js for details concerning isFunction. 504   // Since version 1.3, DOM methods and functions like alert 505   // aren't supported. They return false on IE (#2968). 506   isFunction: function( obj ) { 507     return jQuery.type(obj) === "function"; 508   }, 509  510   isArray: Array.isArray || function( obj ) { 511     return jQuery.type(obj) === "array"; 512   }, 513  514   // A crude way of determining if an object is a window 515   isWindow: function( obj ) { 516     return obj && typeof obj === "object" && "setInterval" in obj; 517   }, 518  519   isNaN: function( obj ) { 520     return obj == null || !rdigit.test( obj ) || isNaN( obj ); 521   }, 522  523   type: function( obj ) { 524     return obj == null ? 525       String( obj ) : 526       class2type[ toString.call(obj) ] || "object"; 527   }, 528  529   isPlainObject: function( obj ) { 530     // Must be an Object. 531     // Because of IE, we also have to check the presence of the constructor property. 532     // Make sure that DOM nodes and window objects don't pass through, as well 533     if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { 534       return false; 535     } 536      537     // Not own constructor property must be Object 538     if ( obj.constructor && 539       !hasOwn.call(obj, "constructor") && 540       !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { 541       return false; 542     } 543      544     // Own properties are enumerated firstly, so to speed up, 545     // if last one is own, then all properties are own. 546    547     var key; 548     for ( key in obj ) {} 549      550     return key === undefined || hasOwn.call( obj, key ); 551   }, 552  553   isEmptyObject: function( obj ) { 554     for ( var name in obj ) { 555       return false; 556     } 557     return true; 558   }, 559    560   error: function( msg ) { 561     throw msg; 562   }, 563    564   parseJSON: function( data ) { 565     if ( typeof data !== "string" || !data ) { 566       return null; 567     } 568  569     // Make sure leading/trailing whitespace is removed (IE can't handle it) 570     data = jQuery.trim( data ); 571      572     // Make sure the incoming data is actual JSON 573     // Logic borrowed from http://json.org/json2.js 574     if ( rvalidchars.test(data.replace(rvalidescape, "@") 575       .replace(rvalidtokens, "]") 576       .replace(rvalidbraces, "")) ) { 577  578       // Try to use the native JSON parser first 579       return window.JSON && window.JSON.parse ? 580         window.JSON.parse( data ) : 581         (new Function("return " + data))(); 582  583     } else { 584       jQuery.error( "Invalid JSON: " + data ); 585     } 586   }, 587  588   noop: function() {}, 589  590   // Evalulates a script in a global context 591   globalEval: function( data ) { 592     if ( data && rnotwhite.test(data) ) { 593       // Inspired by code by Andrea Giammarchi 594       // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html 595       var head = document.getElementsByTagName("head")[0] || document.documentElement, 596         script = document.createElement("script"); 597  598       script.type = "text/javascript"; 599  600       if ( jQuery.support.scriptEval ) { 601         script.appendChild( document.createTextNode( data ) ); 602       } else { 603         script.text = data; 604       } 605  606       // Use insertBefore instead of appendChild to circumvent an IE6 bug. 607       // This arises when a base node is used (#2709). 608       head.insertBefore( script, head.firstChild ); 609       head.removeChild( script ); 610     } 611   }, 612  613   nodeName: function( elem, name ) { 614     return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); 615   }, 616  617   // args is for internal usage only 618   each: function( object, callback, args ) { 619     var name, i = 0, 620       length = object.length, 621       isObj = length === undefined || jQuery.isFunction(object); 622  623     if ( args ) { 624       if ( isObj ) { 625         for ( name in object ) { 626           if ( callback.apply( object[ name ], args ) === false ) { 627             break; 628           } 629         } 630       } else { 631         for ( ; i < length; ) { 632           if ( callback.apply( object[ i++ ], args ) === false ) { 633             break; 634           } 635         } 636       } 637  638     // A special, fast, case for the most common use of each 639     } else { 640       if ( isObj ) { 641         for ( name in object ) { 642           if ( callback.call( object[ name ], name, object[ name ] ) === false ) { 643             break; 644           } 645         } 646       } else { 647         for ( var value = object[0]; 648           i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} 649       } 650     } 651  652     return object; 653   }, 654  655   // Use native String.trim function wherever possible 656   trim: trim ? 657     function( text ) { 658       return text == null ? 659         "" : 660         trim.call( text ); 661     } : 662  663     // Otherwise use our own trimming functionality 664     function( text ) { 665       return text == null ? 666         "" : 667         text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); 668     }, 669  670   // results is for internal usage only 671   makeArray: function( array, results ) { 672     var ret = results || []; 673  674     if ( array != null ) { 675       // The window, strings (and functions) also have 'length' 676       // The extra typeof function check is to prevent crashes 677       // in Safari 2 (See: #3039) 678       // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 679       var type = jQuery.type(array); 680  681       if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { 682         push.call( ret, array ); 683       } else { 684         jQuery.merge( ret, array ); 685       } 686     } 687  688     return ret; 689   }, 690  691   inArray: function( elem, array ) { 692     if ( array.indexOf ) { 693       return array.indexOf( elem ); 694     } 695  696     for ( var i = 0, length = array.length; i < length; i++ ) { 697       if ( array[ i ] === elem ) { 698         return i; 699       } 700     } 701  702     return -1; 703   }, 704  705   merge: function( first, second ) { 706     var i = first.length, 707       j = 0; 708  709     if ( typeof second.length === "number" ) { 710       for ( var l = second.length; j < l; j++ ) { 711         first[ i++ ] = second[ j ]; 712       } 713      714     } else { 715       while ( second[j] !== undefined ) { 716         first[ i++ ] = second[ j++ ]; 717       } 718     } 719  720     first.length = i; 721  722     return first; 723   }, 724  725   grep: function( elems, callback, inv ) { 726     var ret = [], retVal; 727     inv = !!inv; 728  729     // Go through the array, only saving the items 730     // that pass the validator function 731     for ( var i = 0, length = elems.length; i < length; i++ ) { 732       retVal = !!callback( elems[ i ], i ); 733       if ( inv !== retVal ) { 734         ret.push( elems[ i ] ); 735       } 736     } 737  738     return ret; 739   }, 740  741   // arg is for internal usage only 742   map: function( elems, callback, arg ) { 743     var ret = [], value; 744  745     // Go through the array, translating each of the items to their 746     // new value (or values). 747     for ( var i = 0, length = elems.length; i < length; i++ ) { 748       value = callback( elems[ i ], i, arg ); 749  750       if ( value != null ) { 751         ret[ ret.length ] = value; 752       } 753     } 754  755     return ret.concat.apply( [], ret ); 756   }, 757  758   // A global GUID counter for objects 759   guid: 1, 760  761   proxy: function( fn, proxy, thisObject ) { 762     if ( arguments.length === 2 ) { 763       if ( typeof proxy === "string" ) { 764         thisObject = fn; 765         fn = thisObject[ proxy ]; 766         proxy = undefined; 767  768       } else if ( proxy && !jQuery.isFunction( proxy ) ) { 769         thisObject = proxy; 770         proxy = undefined; 771       } 772     } 773  774     if ( !proxy && fn ) { 775       proxy = function() { 776         return fn.apply( thisObject || this, arguments ); 777       }; 778     } 779  780     // Set the guid of unique handler to the same of original handler, so it can be removed 781     if ( fn ) { 782       proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; 783     } 784  785     // So proxy can be declared as an argument 786     return proxy; 787   }, 788  789   // Mutifunctional method to get and set values to a collection 790   // The value/s can be optionally by executed if its a function 791   access: function( elems, key, value, exec, fn, pass ) { 792     var length = elems.length; 793    794     // Setting many attributes 795     if ( typeof key === "object" ) { 796       for ( var k in key ) { 797         jQuery.access( elems, k, key[k], exec, fn, value ); 798       } 799       return elems; 800     } 801    802     // Setting one attribute 803     if ( value !== undefined ) { 804       // Optionally, function values get executed if exec is true 805       exec = !pass && exec && jQuery.isFunction(value); 806      807       for ( var i = 0; i < length; i++ ) { 808         fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); 809       } 810      811       return elems; 812     } 813    814     // Getting an attribute 815     return length ? fn( elems[0], key ) : undefined; 816   }, 817  818   now: function() { 819     return (new Date()).getTime(); 820   }, 821  822   // Use of jQuery.browser is frowned upon. 823   // More details: http://docs.jquery.com/Utilities/jQuery.browser 824   uaMatch: function( ua ) { 825     ua = ua.toLowerCase(); 826  827     var match = rwebkit.exec( ua ) || 828       ropera.exec( ua ) || 829       rmsie.exec( ua ) || 830       ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || 831       []; 832  833     return { browser: match[1] || "", version: match[2] || "0" }; 834   }, 835  836   browser: {} 837 }); 838  839 // Populate the class2type map 840 jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { 841   class2type[ "[object " + name + "]" ] = name.toLowerCase(); 842 }); 843  844 browserMatch = jQuery.uaMatch( userAgent ); 845 if ( browserMatch.browser ) { 846   jQuery.browser[ browserMatch.browser ] = true; 847   jQuery.browser.version = browserMatch.version; 848 } 849  850 // Deprecated, use jQuery.browser.webkit instead 851 if ( jQuery.browser.webkit ) { 852   jQuery.browser.safari = true; 853 } 854  855 if ( indexOf ) { 856   jQuery.inArray = function( elem, array ) { 857     return indexOf.call( array, elem ); 858   }; 859 } 860  861 // Verify that \s matches non-breaking spaces 862 // (IE fails on this test) 863 if ( !rwhite.test( "\xA0" ) ) { 864   trimLeft = /^[\s\xA0]+/; 865   trimRight = /[\s\xA0]+$/; 866 } 867  868 // All jQuery objects should point back to these 869 rootjQuery = jQuery(document); 870  871 // Cleanup functions for the document ready method 872 if ( document.addEventListener ) { 873   DOMContentLoaded = function() { 874     document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); 875     jQuery.ready(); 876   }; 877  878 } else if ( document.attachEvent ) { 879   DOMContentLoaded = function() { 880     // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). 881     if ( document.readyState === "complete" ) { 882       document.detachEvent( "onreadystatechange", DOMContentLoaded ); 883       jQuery.ready(); 884     } 885   }; 886 } 887  888 // The DOM ready check for Internet Explorer 889 function doScrollCheck() { 890   if ( jQuery.isReady ) { 891     return; 892   } 893  894   try { 895     // If IE is used, use the trick by Diego Perini 896     // http://javascript.nwbox.com/IEContentLoaded/ 897     document.documentElement.doScroll("left"); 898   } catch(e) { 899     setTimeout( doScrollCheck, 1 ); 900     return; 901   } 902  903   // and execute any waiting functions 904   jQuery.ready(); 905 } 906  907 // Expose jQuery to the global object 908 return (window.jQuery = window.$ = jQuery); 909  910 })(); 911  912  913 (function() { 914  915   jQuery.support = {}; 916  917   var root = document.documentElement, 918     script = document.createElement("script"), 919     div = document.createElement("div"), 920     id = "script" + jQuery.now(); 921  922   div.style.display = "none"; 923   div.innerHTML = "  <link/><table></table><a href='http://www.cnblogs.com//a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>"; 924  925   var all = div.getElementsByTagName("*"), 926     a = div.getElementsByTagName("a")[0], 927     select = document.createElement("select"), 928     opt = select.appendChild( document.createElement("option") ); 929  930   // Can't get basic test support 931   if ( !all || !all.length || !a ) { 932     return; 933   } 934  935   jQuery.support = { 936     // IE strips leading whitespace when .innerHTML is used 937     leadingWhitespace: div.firstChild.nodeType === 3, 938  939     // Make sure that tbody elements aren't automatically inserted 940     // IE will insert them into empty tables 941     tbody: !div.getElementsByTagName("tbody").length, 942  943     // Make sure that link elements get serialized correctly by innerHTML 944     // This requires a wrapper element in IE 945     htmlSerialize: !!div.getElementsByTagName("link").length, 946  947     // Get the style information from getAttribute 948     // (IE uses .cssText insted) 949     style: /red/.test( a.getAttribute("style") ), 950  951     // Make sure that URLs aren't manipulated 952     // (IE normalizes it by default) 953     hrefNormalized: a.getAttribute("href") === "/a", 954  955     // Make sure that element opacity exists 956     // (IE uses filter instead) 957     // Use a regex to work around a WebKit issue. See #5145 958     opacity: /^0.55$/.test( a.style.opacity ), 959  960     // Verify style float existence 961     // (IE uses styleFloat instead of cssFloat) 962     cssFloat: !!a.style.cssFloat, 963  964     // Make sure that if no value is specified for a checkbox 965     // that it defaults to "on". 966     // (WebKit defaults to "" instead) 967     checkOn: div.getElementsByTagName("input")[0].value === "on", 968  969     // Make sure that a selected-by-default option has a working selected property. 970     // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) 971     optSelected: opt.selected, 972  973     // Will be defined later 974     deleteExpando: true, 975     optDisabled: false, 976     checkClone: false, 977     scriptEval: false, 978     noCloneEvent: true, 979     boxModel: null, 980     inlineBlockNeedsLayout: false, 981     shrinkWrapBlocks: false, 982     reliableHiddenOffsets: true 983   }; 984  985   // Make sure that the options inside disabled selects aren't marked as disabled 986   // (WebKit marks them as diabled) 987   select.disabled = true; 988   jQuery.support.optDisabled = !opt.disabled; 989  990   script.type = "text/javascript"; 991   try { 992     script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); 993   } catch(e) {} 994  995   root.insertBefore( script, root.firstChild ); 996  997   // Make sure that the execution of code works by injecting a script 998   // tag with appendChild/createTextNode 999   // (IE doesn't support this, fails, and uses .text instead)1000   if ( window[ id ] ) {1001     jQuery.support.scriptEval = true;1002     delete window[ id ];1003   }1004 1005   // Test to see if it's possible to delete an expando from an element1006   // Fails in Internet Explorer1007   try {1008     delete script.test;1009 1010   } catch(e) {1011     jQuery.support.deleteExpando = false;1012   }1013 1014   root.removeChild( script );1015 1016   if ( div.attachEvent && div.fireEvent ) {1017     div.attachEvent("onclick", function click() {1018       // Cloning a node shouldn't copy over any1019       // bound event handlers (IE does this)1020       jQuery.support.noCloneEvent = false;1021       div.detachEvent("onclick", click);1022     });1023     div.cloneNode(true).fireEvent("onclick");1024   }1025 1026   div = document.createElement("div");1027   div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";1028 1029   var fragment = document.createDocumentFragment();1030   fragment.appendChild( div.firstChild );1031 1032   // WebKit doesn't clone checked state correctly in fragments1033   jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;1034 1035   // Figure out if the W3C box model works as expected1036   // document.body must exist before we can do this1037   jQuery(function() {1038     var div = document.createElement("div");1039     div.style.width = div.style.paddingLeft = "1px";1040 1041     document.body.appendChild( div );1042     jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;1043 1044     if ( "zoom" in div.style ) {1045       // Check if natively block-level elements act like inline-block1046       // elements when setting their display to 'inline' and giving1047       // them layout1048       // (IE < 8 does this)1049       div.style.display = "inline";1050       div.style.zoom = 1;1051       jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2;1052 1053       // Check if elements with layout shrink-wrap their children1054       // (IE 6 does this)1055       div.style.display = "";1056       div.innerHTML = "<div style='width:4px;'></div>";1057       jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;1058     }1059 1060     div.innerHTML = "<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";1061     var tds = div.getElementsByTagName("td");1062 1063     // Check if table cells still have offsetWidth/Height when they are set1064     // to display:none and there are still other visible table cells in a1065     // table row; if so, offsetWidth/Height are not reliable for use when1066     // determining if an element has been hidden directly using1067     // display:none (it is still safe to use offsets if a parent element is1068     // hidden; don safety goggles and see bug #4512 for more information).1069     // (only IE 8 fails this test)1070     jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0;1071 1072     tds[0].style.display = "";1073     tds[1].style.display = "none";1074 1075     // Check if empty table cells still have offsetWidth/Height1076     // (IE < 8 fail this test)1077     jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0;1078     div.innerHTML = "";1079 1080     document.body.removeChild( div ).style.display = "none";1081     div = tds = null;1082   });1083 1084   // Technique from Juriy Zaytsev1085   // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/1086   var eventSupported = function( eventName ) {1087     var el = document.createElement("div");1088     eventName = "on" + eventName;1089 1090     var isSupported = (eventName in el);1091     if ( !isSupported ) {1092       el.setAttribute(eventName, "return;");1093       isSupported = typeof el[eventName] === "function";1094     }1095     el = null;1096 1097     return isSupported;1098   };1099 1100   jQuery.support.submitBubbles = eventSupported("submit");1101   jQuery.support.changeBubbles = eventSupported("change");1102 1103   // release memory in IE1104   root = script = div = all = a = null;1105 })();1106 1107 1108 1109 var windowData = {},1110   rbrace = /^(?:\{.*\}|\[.*\])$/;1111 1112 jQuery.extend({1113   cache: {},1114 1115   // Please use with caution1116   uuid: 0,1117 1118   // Unique for each copy of jQuery on the page  1119   expando: "jQuery" + jQuery.now(),1120 1121   // The following elements throw uncatchable exceptions if you1122   // attempt to add expando properties to them.1123   noData: {1124     "embed": true,1125     // Ban all objects except for Flash (which handle expandos)1126     "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",1127     "applet": true1128   },1129 1130   data: function( elem, name, data ) {1131     if ( !jQuery.acceptData( elem ) ) {1132       return;1133     }1134 1135     elem = elem == window ?1136       windowData :1137       elem;1138 1139     var isNode = elem.nodeType,1140       id = isNode ? elem[ jQuery.expando ] : null,1141       cache = jQuery.cache, thisCache;1142 1143     if ( isNode && !id && typeof name === "string" && data === undefined ) {1144       return;1145     }1146 1147     // Get the data from the object directly1148     if ( !isNode ) {1149       cache = elem;1150 1151     // Compute a unique ID for the element1152     } else if ( !id ) {1153       elem[ jQuery.expando ] = id = ++jQuery.uuid;1154     }1155 1156     // Avoid generating a new cache unless none exists and we1157     // want to manipulate it.1158     if ( typeof name === "object" ) {1159       if ( isNode ) {1160         cache[ id ] = jQuery.extend(cache[ id ], name);1161 1162       } else {1163         jQuery.extend( cache, name );1164       }1165 1166     } else if ( isNode && !cache[ id ] ) {1167       cache[ id ] = {};1168     }1169 1170     thisCache = isNode ? cache[ id ] : cache;1171 1172     // Prevent overriding the named cache with undefined values1173     if ( data !== undefined ) {1174       thisCache[ name ] = data;1175     }1176 1177     return typeof name === "string" ? thisCache[ name ] : thisCache;1178   },1179 1180   removeData: function( elem, name ) {1181     if ( !jQuery.acceptData( elem ) ) {1182       return;1183     }1184 1185     elem = elem == window ?1186       windowData :1187       elem;1188 1189     var isNode = elem.nodeType,1190       id = isNode ? elem[ jQuery.expando ] : elem,1191       cache = jQuery.cache,1192       thisCache = isNode ? cache[ id ] : id;1193 1194     // If we want to remove a specific section of the element's data1195     if ( name ) {1196       if ( thisCache ) {1197         // Remove the section of cache data1198         delete thisCache[ name ];1199 1200         // If we've removed all the data, remove the element's cache1201         if ( isNode && jQuery.isEmptyObject(thisCache) ) {1202           jQuery.removeData( elem );1203         }1204       }1205 1206     // Otherwise, we want to remove all of the element's data1207     } else {1208       if ( isNode && jQuery.support.deleteExpando ) {1209         delete elem[ jQuery.expando ];1210 1211       } else if ( elem.removeAttribute ) {1212         elem.removeAttribute( jQuery.expando );1213 1214       // Completely remove the data cache1215       } else if ( isNode ) {1216         delete cache[ id ];1217 1218       // Remove all fields from the object1219       } else {1220         for ( var n in elem ) {1221           delete elem[ n ];1222         }1223       }1224     }1225   },1226 1227   // A method for determining if a DOM node can handle the data expando1228   acceptData: function( elem ) {1229     if ( elem.nodeName ) {1230       var match = jQuery.noData[ elem.nodeName.toLowerCase() ];1231 1232       if ( match ) {1233         return !(match === true || elem.getAttribute("classid") !== match);1234       }1235     }1236 1237     return true;1238   }1239 });1240 1241 jQuery.fn.extend({1242   data: function( key, value ) {1243     var data = null;1244 1245     if ( typeof key === "undefined" ) {1246       if ( this.length ) {1247         var attr = this[0].attributes, name;1248         data = jQuery.data( this[0] );1249 1250         for ( var i = 0, l = attr.length; i < l; i++ ) {1251           name = attr[i].name;1252 1253           if ( name.indexOf( "data-" ) === 0 ) {1254             name = name.substr( 5 );1255             dataAttr( this[0], name, data[ name ] );1256           }1257         }1258       }1259 1260       return data;1261 1262     } else if ( typeof key === "object" ) {1263       return this.each(function() {1264         jQuery.data( this, key );1265       });1266     }1267 1268     var parts = key.split(".");1269     parts[1] = parts[1] ? "." + parts[1] : "";1270 1271     if ( value === undefined ) {1272       data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);1273 1274       // Try to fetch any internally stored data first1275       if ( data === undefined && this.length ) {1276         data = jQuery.data( this[0], key );1277         data = dataAttr( this[0], key, data );1278       }1279 1280       return data === undefined && parts[1] ?1281         this.data( parts[0] ) :1282         data;1283 1284     } else {1285       return this.each(function() {1286         var $this = jQuery( this ),1287           args = [ parts[0], value ];1288 1289         $this.triggerHandler( "setData" + parts[1] + "!", args );1290         jQuery.data( this, key, value );1291         $this.triggerHandler( "changeData" + parts[1] + "!", args );1292       });1293     }1294   },1295 1296   removeData: function( key ) {1297     return this.each(function() {1298       jQuery.removeData( this, key );1299     });1300   }1301 });1302 1303 function dataAttr( elem, key, data ) {1304   // If nothing was found internally, try to fetch any1305   // data from the HTML5 data-* attribute1306   if ( data === undefined && elem.nodeType === 1 ) {1307     data = elem.getAttribute( "data-" + key );1308 1309     if ( typeof data === "string" ) {1310       try {1311         data = data === "true" ? true :1312         data === "false" ? false :1313         data === "null" ? null :1314         !jQuery.isNaN( data ) ? parseFloat( data ) :1315           rbrace.test( data ) ? jQuery.parseJSON( data ) :1316           data;1317       } catch( e ) {}1318 1319       // Make sure we set the data so it isn't changed later1320       jQuery.data( elem, key, data );1321 1322     } else {1323       data = undefined;1324     }1325   }1326 1327   return data;1328 }1329 1330 1331 1332 1333 jQuery.extend({1334   queue: function( elem, type, data ) {1335     if ( !elem ) {1336       return;1337     }1338 1339     type = (type || "fx") + "queue";1340     var q = jQuery.data( elem, type );1341 1342     // Speed up dequeue by getting out quickly if this is just a lookup1343     if ( !data ) {1344       return q || [];1345     }1346 1347     if ( !q || jQuery.isArray(data) ) {1348       q = jQuery.data( elem, type, jQuery.makeArray(data) );1349 1350     } else {1351       q.push( data );1352     }1353 1354     return q;1355   },1356 1357   dequeue: function( elem, type ) {1358     type = type || "fx";1359 1360     var queue = jQuery.queue( elem, type ),1361       fn = queue.shift();1362 1363     // If the fx queue is dequeued, always remove the progress sentinel1364     if ( fn === "inprogress" ) {1365       fn = queue.shift();1366     }1367 1368     if ( fn ) {1369       // Add a progress sentinel to prevent the fx queue from being1370       // automatically dequeued1371       if ( type === "fx" ) {1372         queue.unshift("inprogress");1373       }1374 1375       fn.call(elem, function() {1376         jQuery.dequeue(elem, type);1377       });1378     }1379   }1380 });1381 1382 jQuery.fn.extend({1383   queue: function( type, data ) {1384     if ( typeof type !== "string" ) {1385       data = type;1386       type = "fx";1387     }1388 1389     if ( data === undefined ) {1390       return jQuery.queue( this[0], type );1391     }1392     return this.each(function( i ) {1393       var queue = jQuery.queue( this, type, data );1394 1395       if ( type === "fx" && queue[0] !== "inprogress" ) {1396         jQuery.dequeue( this, type );1397       }1398     });1399   },1400   dequeue: function( type ) {1401     return this.each(function() {1402       jQuery.dequeue( this, type );1403     });1404   },1405 1406   // Based off of the plugin by Clint Helfers, with permission.1407   // http://blindsignals.com/index.php/2009/07/jquery-delay/1408   delay: function( time, type ) {1409     time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;1410     type = type || "fx";1411 1412     return this.queue( type, function() {1413       var elem = this;1414       setTimeout(function() {1415         jQuery.dequeue( elem, type );1416       }, time );1417     });1418   },1419 1420   clearQueue: function( type ) {1421     return this.queue( type || "fx", [] );1422   }1423 });1424 1425 1426 1427 1428 var rclass = /[\n\t]/g,1429   rspaces = /\s+/,1430   rreturn = /\r/g,1431   rspecialurl = /^(?:href|src|style)$/,1432   rtype = /^(?:button|input)$/i,1433   rfocusable = /^(?:button|input|object|select|textarea)$/i,1434   rclickable = /^a(?:rea)?$/i,1435   rradiocheck = /^(?:radio|checkbox)$/i;1436 1437 jQuery.props = {1438   "for": "htmlFor",1439   "class": "className",1440   readonly: "readOnly",1441   maxlength: "maxLength",1442   cellspacing: "cellSpacing",1443   rowspan: "rowSpan",1444   colspan: "colSpan",1445   tabindex: "tabIndex",1446   usemap: "useMap",1447   frameborder: "frameBorder"1448 };1449 1450 jQuery.fn.extend({1451   attr: function( name, value ) {1452     return jQuery.access( this, name, value, true, jQuery.attr );1453   },1454 1455   removeAttr: function( name, fn ) {1456     return this.each(function(){1457       jQuery.attr( this, name, "" );1458       if ( this.nodeType === 1 ) {1459         this.removeAttribute( name );1460       }1461     });1462   },1463 1464   addClass: function( value ) {1465     if ( jQuery.isFunction(value) ) {1466       return this.each(function(i) {1467         var self = jQuery(this);1468         self.addClass( value.call(this, i, self.attr("class")) );1469       });1470     }1471 1472     if ( value && typeof value === "string" ) {1473       var classNames = (value || "").split( rspaces );1474 1475       for ( var i = 0, l = this.length; i < l; i++ ) {1476         var elem = this[i];1477 1478         if ( elem.nodeType === 1 ) {1479           if ( !elem.className ) {1480             elem.className = value;1481 1482           } else {1483             var className = " " + elem.className + " ",1484               setClass = elem.className;1485 1486             for ( var c = 0, cl = classNames.length; c < cl; c++ ) {1487               if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {1488                 setClass += " " + classNames[c];1489               }1490             }1491             elem.className = jQuery.trim( setClass );1492           }1493         }1494       }1495     }1496 1497     return this;1498   },1499 1500   removeClass: function( value ) {1501     if ( jQuery.isFunction(value) ) {1502       return this.each(function(i) {1503         var self = jQuery(this);1504         self.removeClass( value.call(this, i, self.attr("class")) );1505       });1506     }1507 1508     if ( (value && typeof value === "string") || value === undefined ) {1509       var classNames = (value || "").split( rspaces );1510 1511       for ( var i = 0, l = this.length; i < l; i++ ) {1512         var elem = this[i];1513 1514         if ( elem.nodeType === 1 && elem.className ) {1515           if ( value ) {1516             var className = (" " + elem.className + " ").replace(rclass, " ");1517             for ( var c = 0, cl = classNames.length; c < cl; c++ ) {1518               className = className.replace(" " + classNames[c] + " ", " ");1519             }1520             elem.className = jQuery.trim( className );1521 1522           } else {1523             elem.className = "";1524           }1525         }1526       }1527     }1528 1529     return this;1530   },1531 1532   toggleClass: function( value, stateVal ) {1533     var type = typeof value,1534       isBool = typeof stateVal === "boolean";1535 1536     if ( jQuery.isFunction( value ) ) {1537       return this.each(function(i) {1538         var self = jQuery(this);1539         self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );1540       });1541     }1542 1543     return this.each(function() {1544       if ( type === "string" ) {1545         // toggle individual class names1546         var className,1547           i = 0,1548           self = jQuery( this ),1549           state = stateVal,1550           classNames = value.split( rspaces );1551 1552         while ( (className = classNames[ i++ ]) ) {1553           // check each className given, space seperated list1554           state = isBool ? state : !self.hasClass( className );1555           self[ state ? "addClass" : "removeClass" ]( className );1556         }1557 1558       } else if ( type === "undefined" || type === "boolean" ) {1559         if ( this.className ) {1560           // store className if set1561           jQuery.data( this, "__className__", this.className );1562         }1563 1564         // toggle whole className1565         this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";1566       }1567     });1568   },1569 1570   hasClass: function( selector ) {1571     var className = " " + selector + " ";1572     for ( var i = 0, l = this.length; i < l; i++ ) {1573       if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {1574         return true;1575       }1576     }1577 1578     return false;1579   },1580 1581   val: function( value ) {1582     if ( !arguments.length ) {1583       var elem = this[0];1584 1585       if ( elem ) {1586         if ( jQuery.nodeName( elem, "option" ) ) {1587           // attributes.value is undefined in Blackberry 4.7 but1588           // uses .value. See #69321589           var val = elem.attributes.value;1590           return !val || val.specified ? elem.value : elem.text;1591         }1592 1593         // We need to handle select boxes special1594         if ( jQuery.nodeName( elem, "select" ) ) {1595           var index = elem.selectedIndex,1596             values = [],1597             options = elem.options,1598             one = elem.type === "select-one";1599 1600           // Nothing was selected1601           if ( index < 0 ) {1602             return null;1603           }1604 1605           // Loop through all the selected options1606           for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {1607             var option = options[ i ];1608 1609             // Don't return options that are disabled or in a disabled optgroup1610             if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && 1611                 (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {1612 1613               // Get the specific value for the option1614               value = jQuery(option).val();1615 1616               // We don't need an array for one selects1617               if ( one ) {1618                 return value;1619               }1620 1621               // Multi-Selects return an array1622               values.push( value );1623             }1624           }1625 1626           return values;1627         }1628 1629         // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified1630         if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {1631           return elem.getAttribute("value") === null ? "on" : elem.value;1632         }1633         1634 1635         // Everything else, we just grab the value1636         return (elem.value || "").replace(rreturn, "");1637 1638       }1639 1640       return undefined;1641     }1642 1643     var isFunction = jQuery.isFunction(value);1644 1645     return this.each(function(i) {1646       var self = jQuery(this), val = value;1647 1648       if ( this.nodeType !== 1 ) {1649         return;1650       }1651 1652       if ( isFunction ) {1653         val = value.call(this, i, self.val());1654       }1655 1656       // Treat null/undefined as ""; convert numbers to string1657       if ( val == null ) {1658         val = "";1659       } else if ( typeof val === "number" ) {1660         val += "";1661       } else if ( jQuery.isArray(val) ) {1662         val = jQuery.map(val, function (value) {1663           return value == null ? "" : value + "";1664         });1665       }1666 1667       if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {1668         this.checked = jQuery.inArray( self.val(), val ) >= 0;1669 1670       } else if ( jQuery.nodeName( this, "select" ) ) {1671         var values = jQuery.makeArray(val);1672 1673         jQuery( "option", this ).each(function() {1674           this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;1675         });1676 1677         if ( !values.length ) {1678           this.selectedIndex = -1;1679         }1680 1681       } else {1682         this.value = val;1683       }1684     });1685   }1686 });1687 1688 jQuery.extend({1689   attrFn: {1690     val: true,1691     css: true,1692     html: true,1693     text: true,1694     data: true,1695     width: true,1696     height: true,1697     offset: true1698   },1699     1700   attr: function( elem, name, value, pass ) {1701     // don't set attributes on text and comment nodes1702     if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {1703       return undefined;1704     }1705 1706     if ( pass && name in jQuery.attrFn ) {1707       return jQuery(elem)[name](value);1708     }1709 1710     var notjQuery.is1711       // Whether we are setting (or getting)1712       set = value !== undefined;1713 1714     // Try to normalize/fix the name1715     name = not name;1716 1717     // These attributes require special treatment1718     var special = rspecialurl.test( name );1719 1720     // Safari mis-reports the default selected property of an option1721     // Accessing the parent's selectedIndex property fixes it1722     if ( name === "selected" && !jQuery.support.optSelected ) {1723       var parent = elem.parentNode;1724       if ( parent ) {1725         parent.selectedIndex;1726 1727         // Make sure that it also works with optgroups, see #57011728         if ( parent.parentNode ) {1729           parent.parentNode.selectedIndex;1730         }1731       }1732     }1733 1734     // If applicable, access the attribute via the DOM 0 way1735     // 'in' checks fail in Blackberry 4.7 #69311736     if ( (name in elem || elem[ name ] !== undefined) && notspecial ) {1737       if ( set ) {1738         // We can't allow the type property to be changed (since it causes problems in IE)1739         if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {1740           jQuery.error( "type property can't be changed" );1741         }1742 1743         if ( value === null ) {1744           if ( elem.nodeType === 1 ) {1745             elem.removeAttribute( name );1746           }1747 1748         } else {1749           elem[ name ] = value;1750         }1751       }1752 1753       // browsers index elements by id/name on forms, give priority to attributes.1754       if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {1755         return elem.getAttributeNode( name ).nodeValue;1756       }1757 1758       // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set1759       // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/1760       if ( name === "tabIndex" ) {1761         var attributeNode = elem.getAttributeNode( "tabIndex" );1762 1763         return attributeNode && attributeNode.specified ?1764           attributeNode.value :1765           rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?1766             0 :1767             undefined;1768       }1769 1770       return elem[ name ];1771     }1772 1773     if ( !jQuery.support.style && not ) {1774       if ( set ) {1775         elem.style.cssText = "" + value;1776       }1777 1778       return elem.style.cssText;1779     }1780 1781     if ( set ) {1782       // convert the value to a string (all browsers do this but IE) see #10701783       elem.setAttribute( name, "" + value );1784     }1785 1786     // Ensure that missing attributes return undefined1787     // Blackberry 4.7 returns "" from getAttribute #69381788     if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) {1789       return undefined;1790     }1791 1792     var attr = !jQuery.support.hrefNormalized && not1793         // Some attributes require a special call on IE1794         elem.getAttribute( name, 2 ) :1795         elem.getAttribute( name );1796 1797     // Non-existent attributes return null, we normalize to undefined1798     return attr === null ? undefined : attr;1799   }1800 });1801 1802 1803 1804 1805 var rnamespaces = /\.(.*)$/,1806   rformElems = /^(?:textarea|input|select)$/i,1807   rperiod = /\./g,1808   rspace = / /g,1809   rescape = /[^\w\s.|`]/g,1810   fcleanup = function( nm ) {1811     return nm.replace(rescape, "\\$&");1812   },1813   focusCounts = { focusin: 0, focusout: 0 };1814 1815 /*1816  * A number of helper functions used for managing events.1817  * Many of the ideas behind this code originated from1818  * Dean Edwards' addEvent library.1819 */1820 jQuery.event = {1821 1822   // Bind an event to an element1823   // Original by Dean Edwards1824   add: function( elem, types, handler, data ) {1825     if ( elem.nodeType === 3 || elem.nodeType === 8 ) {1826       return;1827     }1828 1829     // For whatever reason, IE has trouble passing the window object1830     // around, causing it to be cloned in the process1831     if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {1832       elem = window;1833     }1834 1835     if ( handler === false ) {1836       handler = returnFalse;1837     } else if ( !handler ) {1838       // Fixes bug #7229. Fix recommended by jdalton1839      return;1840     }1841 1842     var handleObjIn, handleObj;1843 1844     if ( handler.handler ) {1845       handleObjIn = handler;1846       handler = handleObjIn.handler;1847     }1848 1849     // Make sure that the function being executed has a unique ID1850     if ( !handler.guid ) {1851       handler.guid = jQuery.guid++;1852     }1853 1854     // Init the element's event structure1855     var elemData = jQuery.data( elem );1856 1857     // If no elemData is found then we must be trying to bind to one of the1858     // banned noData elements1859     if ( !elemData ) {1860       return;1861     }1862 1863     // Use a key less likely to result in collisions for plain JS objects.1864     // Fixes bug #7150.1865     var eventKey = elem.nodeType ? "events" : "__events__",1866       events = elemData[ eventKey ],1867       eventHandle = elemData.handle;1868       1869     if ( typeof events === "function" ) {1870       // On plain objects events is a fn that holds the the data1871       // which prevents this data from being JSON serialized1872       // the function does not need to be called, it just contains the data1873       eventHandle = events.handle;1874       events = events.events;1875 1876     } else if ( !events ) {1877       if ( !elem.nodeType ) {1878         // On plain objects, create a fn that acts as the holder1879         // of the values to avoid JSON serialization of event data1880         elemData[ eventKey ] = elemData = function(){};1881       }1882 1883       elemData.events = events = {};1884     }1885 1886     if ( !eventHandle ) {1887       elemData.handle = eventHandle = function() {1888         // Handle the second event of a trigger and when1889         // an event is called after a page has unloaded1890         return typeof jQuery !== "undefined" && !jQuery.event.triggered ?1891           jQuery.event.handle.apply( eventHandle.elem, arguments ) :1892           undefined;1893       };1894     }1895 1896     // Add elem as a property of the handle function1897     // This is to prevent a memory leak with non-native events in IE.1898     eventHandle.elem = elem;1899 1900     // Handle multiple events separated by a space1901     // jQuery(...).bind("mouseover mouseout", fn);1902     types = types.split(" ");1903 1904     var type, i = 0, namespaces;1905 1906     while ( (type = types[ i++ ]) ) {1907       handleObj = handleObjIn ?1908         jQuery.extend({}, handleObjIn) :1909         { handler: handler, data: data };1910 1911       // Namespaced event handlers1912       if ( type.indexOf(".") > -1 ) {1913         namespaces = type.split(".");1914         type = namespaces.shift();1915         handleObj.namespace = namespaces.slice(0).sort().join(".");1916 1917       } else {1918         namespaces = [];1919         handleObj.namespace = "";1920       }1921 1922       handleObj.type = type;1923       if ( !handleObj.guid ) {1924         handleObj.guid = handler.guid;1925       }1926 1927       // Get the current list of functions bound to this event1928       var handlers = events[ type ],1929         special = jQuery.event.special[ type ] || {};1930 1931       // Init the event handler queue1932       if ( !handlers ) {1933         handlers = events[ type ] = [];1934 1935         // Check for a special event handler1936         // Only use addEventListener/attachEvent if the special1937         // events handler returns false1938         if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {1939           // Bind the global event handler to the element1940           if ( elem.addEventListener ) {1941             elem.addEventListener( type, eventHandle, false );1942 1943           } else if ( elem.attachEvent ) {1944             elem.attachEvent( "on" + type, eventHandle );1945           }1946         }1947       }1948       1949       if ( special.add ) { 1950         special.add.call( elem, handleObj ); 1951 1952         if ( !handleObj.handler.guid ) {1953           handleObj.handler.guid = handler.guid;1954         }1955       }1956 1957       // Add the function to the element's handler list1958       handlers.push( handleObj );1959 1960       // Keep track of which events have been used, for global triggering1961       jQuery.event.global[ type ] = true;1962     }1963 1964     // Nullify elem to prevent memory leaks in IE1965     elem = null;1966   },1967 1968   global: {},1969 1970   // Detach an event or set of events from an element1971   remove: function( elem, types, handler, pos ) {1972     // don't do events on text and comment nodes1973     if ( elem.nodeType === 3 || elem.nodeType === 8 ) {1974       return;1975     }1976 1977     if ( handler === false ) {1978       handler = returnFalse;1979     }1980 1981     var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,1982       eventKey = elem.nodeType ? "events" : "__events__",1983       elemData = jQuery.data( elem ),1984       events = elemData && elemData[ eventKey ];1985 1986     if ( !elemData || !events ) {1987       return;1988     }1989     1990     if ( typeof events === "function" ) {1991       elemData = events;1992       events = events.events;1993     }1994 1995     // types is actually an event object here1996     if ( types && types.type ) {1997       handler = types.handler;1998       types = types.type;1999     }2000 2001     // Unbind all events for the element2002     if ( !types || typeof types === "string" && types.charAt(0) === "." ) {2003       types = types || "";2004 2005       for ( type in events ) {2006         jQuery.event.remove( elem, type + types );2007       }2008 2009       return;2010     }2011 2012     // Handle multiple events separated by a space2013     // jQuery(...).unbind("mouseover mouseout", fn);2014     types = types.split(" ");2015 2016     while ( (type = types[ i++ ]) ) {2017       origType = type;2018       handleObj = null;2019       all = type.indexOf(".") < 0;2020       namespaces = [];2021 2022       if ( !all ) {2023         // Namespaced event handlers2024         namespaces = type.split(".");2025         type = namespaces.shift();2026 2027         namespace = new RegExp("(^|\\.)" + 2028           jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");2029       }2030 2031       eventType = events[ type ];2032 2033       if ( !eventType ) {2034         continue;2035       }2036 2037       if ( !handler ) {2038         for ( j = 0; j < eventType.length; j++ ) {2039           handleObj = eventType[ j ];2040 2041           if ( all || namespace.test( handleObj.namespace ) ) {2042             jQuery.event.remove( elem, origType, handleObj.handler, j );2043             eventType.splice( j--, 1 );2044           }2045         }2046 2047         continue;2048       }2049 2050       special = jQuery.event.special[ type ] || {};2051 2052       for ( j = pos || 0; j < eventType.length; j++ ) {2053         handleObj = eventType[ j ];2054 2055         if ( handler.guid === handleObj.guid ) {2056           // remove the given handler for the given type2057           if ( all || namespace.test( handleObj.namespace ) ) {2058             if ( pos == null ) {2059               eventType.splice( j--, 1 );2060             }2061 2062             if ( special.remove ) {2063               special.remove.call( elem, handleObj );2064             }2065           }2066 2067           if ( pos != null ) {2068             break;2069           }2070         }2071       }2072 2073       // remove generic event handler if no more handlers exist2074       if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {2075         if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {2076           jQuery.removeEvent( elem, type, elemData.handle );2077         }2078 2079         ret = null;2080         delete events[ type ];2081       }2082     }2083 2084     // Remove the expando if it's no longer used2085     if ( jQuery.isEmptyObject( events ) ) {2086       var handle = elemData.handle;2087       if ( handle ) {2088         handle.elem = null;2089       }2090 2091       delete elemData.events;2092       delete elemData.handle;2093 2094       if ( typeof elemData === "function" ) {2095         jQuery.removeData( elem, eventKey );2096 2097       } else if ( jQuery.isEmptyObject( elemData ) ) {2098         jQuery.removeData( elem );2099       }2100     }2101   },2102 2103   // bubbling is internal2104   trigger: function( event, data, elem /*, bubbling */ ) {2105     // Event object or event type2106     var type = event.type || event,2107       bubbling = arguments[3];2108 2109     if ( !bubbling ) {2110       event = typeof event === "object" ?2111         // jQuery.Event object2112         event[ jQuery.expando ] ? event :2113         // Object literal2114         jQuery.extend( jQuery.Event(type), event ) :2115         // Just the event type (string)2116         jQuery.Event(type);2117 2118       if ( type.indexOf("!") >= 0 ) {2119         event.type = type = type.slice(0, -1);2120         event.exclusive = true;2121       }2122 2123       // Handle a global trigger2124       if ( !elem ) {2125         // Don't bubble custom events when global (to avoid too much overhead)2126         event.stopPropagation();2127 2128         // Only trigger if we've ever bound an event for it2129         if ( jQuery.event.global[ type ] ) {2130           jQuery.each( jQuery.cache, function() {2131             if ( this.events && this.events[type] ) {2132               jQuery.event.trigger( event, data, this.handle.elem );2133             }2134           });2135         }2136       }2137 2138       // Handle triggering a single element2139 2140       // don't do events on text and comment nodes2141       if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {2142         return undefined;2143       }2144 2145       // Clean up in case it is reused2146       event.result = undefined;2147       event.target = elem;2148 2149       // Clone the incoming data, if any2150       data = jQuery.makeArray( data );2151       data.unshift( event );2152     }2153 2154     event.currentTarget = elem;2155 2156     // Trigger the event, it is assumed that "handle" is a function2157     var handle = elem.nodeType ?2158       jQuery.data( elem, "handle" ) :2159       (jQuery.data( elem, "__events__" ) || {}).handle;2160 2161     if ( handle ) {2162       handle.apply( elem, data );2163     }2164 2165     var parent = elem.parentNode || elem.ownerDocument;2166 2167     // Trigger an inline bound script2168     try {2169       if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {2170         if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {2171           event.result = false;2172           event.preventDefault();2173         }2174       }2175 2176     // prevent IE from throwing an error for some elements with some event types, see #35332177     } catch (inlineError) {}2178 2179     if ( !event.isPropagationStopped() && parent ) {2180       jQuery.event.trigger( event, data, parent, true );2181 2182     } else if ( !event.isDefaultPrevented() ) {2183       var old,2184         target = event.target,2185         targetType = type.replace( rnamespaces, "" ),2186         isClick = jQuery.nodeName( target, "a" ) && targetType === "click",2187         special = jQuery.event.special[ targetType ] || {};2188 2189       if ( (!special._default || special._default.call( elem, event ) === false) && 2190         !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {2191 2192         try {2193           if ( target[ targetType ] ) {2194             // Make sure that we don't accidentally re-trigger the onFOO events2195             old = target[ "on" + targetType ];2196 2197             if ( old ) {2198               target[ "on" + targetType ] = null;2199             }2200 2201             jQuery.event.triggered = true;2202             target[ targetType ]();2203           }2204 2205         // prevent IE from throwing an error for some elements with some event types, see #35332206         } catch (triggerError) {}2207 2208         if ( old ) {2209           target[ "on" + targetType ] = old;2210         }2211 2212         jQuery.event.triggered = false;2213       }2214     }2215   },2216 2217   handle: function( event ) {2218     var all, handlers, namespaces, namespace_re, events,2219       namespace_sort = [],2220       args = jQuery.makeArray( arguments );2221 2222     event = args[0] = jQuery.event.fix( event || window.event );2223     event.currentTarget = this;2224 2225     // Namespaced event handlers2226     all = event.type.indexOf(".") < 0 && !event.exclusive;2227 2228     if ( !all ) {2229       namespaces = event.type.split(".");2230       event.type = namespaces.shift();2231       namespace_sort = namespaces.slice(0).sort();2232       namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");2233     }2234 2235     event.namespace = event.namespace || namespace_sort.join(".");2236 2237     events = jQuery.data(this, this.nodeType ? "events" : "__events__");2238 2239     if ( typeof events === "function" ) {2240       events = events.events;2241     }2242 2243     handlers = (events || {})[ event.type ];2244 2245     if ( events && handlers ) {2246       // Clone the handlers to prevent manipulation2247       handlers = handlers.slice(0);2248 2249       for ( var j = 0, l = handlers.length; j < l; j++ ) {2250         var handleObj = handlers[ j ];2251 2252         // Filter the functions by class2253         if ( all || namespace_re.test( handleObj.namespace ) ) {2254           // Pass in a reference to the handler function itself2255           // So that we can later remove it2256           event.handler = handleObj.handler;2257           event.data = handleObj.data;2258           event.handleObj = handleObj;2259   2260           var ret = handleObj.handler.apply( this, args );2261 2262           if ( ret !== undefined ) {2263             event.result = ret;2264             if ( ret === false ) {2265               event.preventDefault();2266               event.stopPropagation();2267             }2268           }2269 2270           if ( event.isImmediatePropagationStopped() ) {2271             break;2272           }2273         }2274       }2275     }2276 2277     return event.result;2278   },2279 2280   props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),2281 2282   fix: function( event ) {2283     if ( event[ jQuery.expando ] ) {2284       return event;2285     }2286 2287     // store a copy of the original event object2288     // and "clone" to set read-only properties2289     var originalEvent = event;2290     event = jQuery.Event( originalEvent );2291 2292     for ( var i = this.props.length, prop; i; ) {2293       prop = this.props[ --i ];2294       event[ prop ] = originalEvent[ prop ];2295     }2296 2297     // Fix target property, if necessary2298     if ( !event.target ) {2299       // Fixes #1925 where srcElement might not be defined either2300       event.target = event.srcElement || document;2301     }2302 2303     // check if target is a textnode (safari)2304     if ( event.target.nodeType === 3 ) {2305       event.target = event.target.parentNode;2306     }2307 2308     // Add relatedTarget, if necessary2309     if ( !event.relatedTarget && event.fromElement ) {2310       event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;2311     }2312 2313     // Calculate pageX/Y if missing and clientX/Y available2314     if ( event.pageX == null && event.clientX != null ) {2315       var doc = document.documentElement,2316         body = document.body;2317 2318       event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);2319       event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);2320     }2321 2322     // Add which for key events2323     if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {2324       event.which = event.charCode != null ? event.charCode : event.keyCode;2325     }2326 2327     // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)2328     if ( !event.metaKey && event.ctrlKey ) {2329       event.metaKey = event.ctrlKey;2330     }2331 2332     // Add which for click: 1 === left; 2 === middle; 3 === right2333     // Note: button is not normalized, so don't use it2334     if ( !event.which && event.button !== undefined ) {2335       event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));2336     }2337 2338     return event;2339   },2340 2341   // Deprecated, use jQuery.guid instead2342   guid: 1E8,2343 2344   // Deprecated, use jQuery.proxy instead2345   proxy: jQuery.proxy,2346 2347   special: {2348     ready: {2349       // Make sure the ready event is setup2350       setup: jQuery.bindReady,2351       teardown: jQuery.noop2352     },2353 2354     live: {2355       add: function( handleObj ) {2356         jQuery.event.add( this,2357           liveConvert( handleObj.origType, handleObj.selector ),2358           jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); 2359       },2360 2361       remove: function( handleObj ) {2362         jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );2363       }2364     },2365 2366     beforeunload: {2367       setup: function( data, namespaces, eventHandle ) {2368         // We only want to do this special case on windows2369         if ( jQuery.isWindow( this ) ) {2370           this.onbeforeunload = eventHandle;2371         }2372       },2373 2374       teardown: function( namespaces, eventHandle ) {2375         if ( this.onbeforeunload === eventHandle ) {2376           this.onbeforeunload = null;2377         }2378       }2379     }2380   }2381 };2382 2383 jQuery.removeEvent = document.removeEventListener ?2384   function( elem, type, handle ) {2385     if ( elem.removeEventListener ) {2386       elem.removeEventListener( type, handle, false );2387     }2388   } : 2389   function( elem, type, handle ) {2390     if ( elem.detachEvent ) {2391       elem.detachEvent( "on" + type, handle );2392     }2393   };2394 2395 jQuery.Event = function( src ) {2396   // Allow instantiation without the 'new' keyword2397   if ( !this.preventDefault ) {2398     return new jQuery.Event( src );2399   }2400 2401   // Event object2402   if ( src && src.type ) {2403     this.originalEvent = src;2404     this.type = src.type;2405   // Event type2406   } else {2407     this.type = src;2408   }2409 2410   // timeStamp is buggy for some events on Firefox(#3843)2411   // So we won't rely on the native value2412   this.timeStamp = jQuery.now();2413 2414   // Mark it as fixed2415   this[ jQuery.expando ] = true;2416 };2417 2418 function returnFalse() {2419   return false;2420 }2421 function returnTrue() {2422   return true;2423 }2424 2425 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding2426 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html2427 jQuery.Event.prototype = {2428   preventDefault: function() {2429     this.isDefaultPrevented = returnTrue;2430 2431     var e = this.originalEvent;2432     if ( !e ) {2433       return;2434     }2435     2436     // if preventDefault exists run it on the original event2437     if ( e.preventDefault ) {2438       e.preventDefault();2439 2440     // otherwise set the returnValue property of the original event to false (IE)2441     } else {2442       e.returnValue = false;2443     }2444   },2445   stopPropagation: function() {2446     this.isPropagationStopped = returnTrue;2447 2448     var e = this.originalEvent;2449     if ( !e ) {2450       return;2451     }2452     // if stopPropagation exists run it on the original event2453     if ( e.stopPropagation ) {2454       e.stopPropagation();2455     }2456     // otherwise set the cancelBubble property of the original event to true (IE)2457     e.cancelBubble = true;2458   },2459   stopImmediatePropagation: function() {2460     this.isImmediatePropagationStopped = returnTrue;2461     this.stopPropagation();2462   },2463   isDefaultPrevented: returnFalse,2464   isPropagationStopped: returnFalse,2465   isImmediatePropagationStopped: returnFalse2466 };2467 2468 // Checks if an event happened on an element within another element2469 // Used in jQuery.event.special.mouseenter and mouseleave handlers2470 var withinElement = function( event ) {2471   // Check if mouse(over|out) are still within the same parent element2472   var parent = event.relatedTarget;2473 2474   // Firefox sometimes assigns relatedTarget a XUL element2475   // which we cannot access the parentNode property of2476   try {2477     // Traverse up the tree2478     while ( parent && parent !== this ) {2479       parent = parent.parentNode;2480     }2481 2482     if ( parent !== this ) {2483       // set the correct event type2484       event.type = event.data;2485 2486       // handle event if we actually just moused on to a non sub-element2487       jQuery.event.handle.apply( this, arguments );2488     }2489 2490   // assuming we've left the element since we most likely mousedover a xul element2491   } catch(e) { }2492 },2493 2494 // In case of event delegation, we only need to rename the event.type,2495 // liveHandler will take care of the rest.2496 delegate = function( event ) {2497   event.type = event.data;2498   jQuery.event.handle.apply( this, arguments );2499 };2500 2501 // Create mouseenter and mouseleave events2502 jQuery.each({2503   mouseenter: "mouseover",2504   mouseleave: "mouseout"2505 }, function( orig, fix ) {2506   jQuery.event.special[ orig ] = {2507     setup: function( data ) {2508       jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );2509     },2510     teardown: function( data ) {2511       jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );2512     }2513   };2514 });2515 2516 // submit delegation2517 if ( !jQuery.support.submitBubbles ) {2518 2519   jQuery.event.special.submit = {2520     setup: function( data, namespaces ) {2521       if ( this.nodeName.toLowerCase() !== "form" ) {2522         jQuery.event.add(this, "click.specialSubmit", function( e ) {2523           var elem = e.target,2524             type = elem.type;2525 2526           if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {2527             e.liveFired = undefined;2528             return trigger( "submit", this, arguments );2529           }2530         });2531   2532         jQuery.event.add(this, "keypress.specialSubmit", function( e ) {2533           var elem = e.target,2534             type = elem.type;2535 2536           if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {2537             e.liveFired = undefined;2538             return trigger( "submit", this, arguments );2539           }2540         });2541 2542       } else {2543         return false;2544       }2545     },2546 2547     teardown: function( namespaces ) {2548       jQuery.event.remove( this, ".specialSubmit" );2549     }2550   };2551 2552 }2553 2554 // change delegation, happens here so we have bind.2555 if ( !jQuery.support.changeBubbles ) {2556 2557   var changeFilters,2558 2559   getVal = function( elem ) {2560     var type = elem.type, val = elem.value;2561 2562     if ( type === "radio" || type === "checkbox" ) {2563       val = elem.checked;2564 2565     } else if ( type === "select-multiple" ) {2566       val = elem.selectedIndex > -1 ?2567         jQuery.map( elem.options, function( elem ) {2568           return elem.selected;2569         }).join("-") :2570         "";2571 2572     } else if ( elem.nodeName.toLowerCase() === "select" ) {2573       val = elem.selectedIndex;2574     }2575 2576     return val;2577   },2578 2579   testChange = function testChange( e ) {2580     var elem = e.target, data, val;2581 2582     if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {2583       return;2584     }2585 2586     data = jQuery.data( elem, "_change_data" );2587     val = getVal(elem);2588 2589     // the current data will be also retrieved by beforeactivate2590     if ( e.type !== "focusout" || elem.type !== "radio" ) {2591       jQuery.data( elem, "_change_data", val );2592     }2593     2594     if ( data === undefined || val === data ) {2595       return;2596     }2597 2598     if ( data != null || val ) {2599       e.type = "change";2600       e.liveFired = undefined;2601       return jQuery.event.trigger( e, arguments[1], elem );2602     }2603   };2604 2605   jQuery.event.special.change = {2606     filters: {2607       focusout: testChange, 2608 2609       beforedeactivate: testChange,2610 2611       click: function( e ) {2612         var elem = e.target, type = elem.type;2613 2614         if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {2615           return testChange.call( this, e );2616         }2617       },2618 2619       // Change has to be called before submit2620       // Keydown will be called before keypress, which is used in submit-event delegation2621       keydown: function( e ) {2622         var elem = e.target, type = elem.type;2623 2624         if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||2625           (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||2626           type === "select-multiple" ) {2627           return testChange.call( this, e );2628         }2629       },2630 2631       // Beforeactivate happens also before the previous element is blurred2632       // with this event you can't trigger a change event, but you can store2633       // information2634       beforeactivate: function( e ) {2635         var elem = e.target;2636         jQuery.data( elem, "_change_data", getVal(elem) );2637       }2638     },2639 2640     setup: function( data, namespaces ) {2641       if ( this.type === "file" ) {2642         return false;2643       }2644 2645       for ( var type in changeFilters ) {2646         jQuery.event.add( this, type + ".specialChange", changeFilters[type] );2647       }2648 2649       return rformElems.test( this.nodeName );2650     },2651 2652     teardown: function( namespaces ) {2653       jQuery.event.remove( this, ".specialChange" );2654 2655       return rformElems.test( this.nodeName );2656     }2657   };2658 2659   changeFilters = jQuery.event.special.change.filters;2660 2661   // Handle when the input is .focus()'d2662   changeFilters.focus = changeFilters.beforeactivate;2663 }2664 2665 function trigger( type, elem, args ) {2666   args[0].type = type;2667   return jQuery.event.handle.apply( elem, args );2668 }2669 2670 // Create "bubbling" focus and blur events2671 if ( document.addEventListener ) {2672   jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {2673     jQuery.event.special[ fix ] = {2674       setup: function() {2675         if ( focusCounts[fix]++ === 0 ) {2676           document.addEventListener( orig, handler, true );2677         }2678       }, 2679       teardown: function() { 2680         if ( --focusCounts[fix] === 0 ) {2681           document.removeEventListener( orig, handler, true );2682         }2683       }2684     };2685 2686     function handler( e ) { 2687       e = jQuery.event.fix( e );2688       e.type = fix;2689       return jQuery.event.trigger( e, null, e.target );2690     }2691   });2692 }2693 2694 jQuery.each(["bind", "one"], function( i, name ) {2695   jQuery.fn[ name ] = function( type, data, fn ) {2696     // Handle object literals2697     if ( typeof type === "object" ) {2698       for ( var key in type ) {2699         this[ name ](key, data, type[key], fn);2700       }2701       return this;2702     }2703     2704     if ( jQuery.isFunction( data ) || data === false ) {2705       fn = data;2706       data = undefined;2707     }2708 2709     var handler = name === "one" ? jQuery.proxy( fn, function( event ) {2710       jQuery( this ).unbind( event, handler );2711       return fn.apply( this, arguments );2712     }) : fn;2713 2714     if ( type === "unload" && name !== "one" ) {2715       this.one( type, data, fn );2716 2717     } else {2718       for ( var i = 0, l = this.length; i < l; i++ ) {2719         jQuery.event.add( this[i], type, handler, data );2720       }2721     }2722 2723     return this;2724   };2725 });2726 2727 jQuery.fn.extend({2728   unbind: function( type, fn ) {2729     // Handle object literals2730     if ( typeof type === "object" && !type.preventDefault ) {2731       for ( var key in type ) {2732         this.unbind(key, type[key]);2733       }2734 2735     } else {2736       for ( var i = 0, l = this.length; i < l; i++ ) {2737         jQuery.event.remove( this[i], type, fn );2738       }2739     }2740 2741     return this;2742   },2743   2744   delegate: function( selector, types, data, fn ) {2745     return this.live( types, data, fn, selector );2746   },2747   2748   undelegate: function( selector, types, fn ) {2749     if ( arguments.length === 0 ) {2750         return this.unbind( "live" );2751     2752     } else {2753       return this.die( types, null, fn, selector );2754     }2755   },2756   2757   trigger: function( type, data ) {2758     return this.each(function() {2759       jQuery.event.trigger( type, data, this );2760     });2761   },2762 2763   triggerHandler: function( type, data ) {2764     if ( this[0] ) {2765       var event = jQuery.Event( type );2766       event.preventDefault();2767       event.stopPropagation();2768       jQuery.event.trigger( event, data, this[0] );2769       return event.result;2770     }2771   },2772 2773   toggle: function( fn ) {2774     // Save reference to arguments for access in closure2775     var args = arguments,2776       i = 1;2777 2778     // link all the functions, so any of them can unbind this click handler2779     while ( i < args.length ) {2780       jQuery.proxy( fn, args[ i++ ] );2781     }2782 2783     return this.click( jQuery.proxy( fn, function( event ) {2784       // Figure out which function to execute2785       var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;2786       jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );2787 2788       // Make sure that clicks stop2789       event.preventDefault();2790 2791       // and execute the function2792       return args[ lastToggle ].apply( this, arguments ) || false;2793     }));2794   },2795 2796   hover: function( fnOver, fnOut ) {2797     return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );2798   }2799 });2800 2801 var liveMap = {2802   focus: "focusin",2803   blur: "focusout",2804   mouseenter: "mouseover",2805   mouseleave: "mouseout"2806 };2807 2808 jQuery.each(["live", "die"], function( i, name ) {2809   jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {2810     var type, i = 0, match, namespaces, preType,2811       selector = origSelector || this.selector,2812       context = origSelector ? this : jQuery( this.context );2813     2814     if ( typeof types === "object" && !types.preventDefault ) {2815       for ( var key in types ) {2816         context[ name ]( key, data, types[key], selector );2817       }2818       2819       return this;2820     }2821 2822     if ( jQuery.isFunction( data ) ) {2823       fn = data;2824       data = undefined;2825     }2826 2827     types = (types || "").split(" ");2828 2829     while ( (type = types[ i++ ]) != null ) {2830       match = rnamespaces.exec( type );2831       namespaces = "";2832 2833       if ( match ) {2834         namespaces = match[0];2835         type = type.replace( rnamespaces, "" );2836       }2837 2838       if ( type === "hover" ) {2839         types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );2840         continue;2841       }2842 2843       preType = type;2844 2845       if ( type === "focus" || type === "blur" ) {2846         types.push( liveMap[ type ] + namespaces );2847         type = type + namespaces;2848 2849       } else {2850         type = (liveMap[ type ] || type) + namespaces;2851       }2852 2853       if ( name === "live" ) {2854         // bind live handler2855         for ( var j = 0, l = context.length; j < l; j++ ) {2856           jQuery.event.add( context[j], "live." + liveConvert( type, selector ),2857             { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );2858         }2859 2860       } else {2861         // unbind live handler2862         context.unbind( "live." + liveConvert( type, selector ), fn );2863       }2864     }2865     2866     return this;2867   };2868 });2869 2870 function liveHandler( event ) {2871   var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,2872     elems = [],2873     selectors = [],2874     events = jQuery.data( this, this.nodeType ? "events" : "__events__" );2875 2876   if ( typeof events === "function" ) {2877     events = events.events;2878   }2879 2880   // Make sure we avoid non-left-click bubbling in Firefox (#3861)2881   if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {2882     return;2883   }2884   2885   if ( event.namespace ) {2886     namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");2887   }2888 2889   event.liveFired = this;2890 2891   var live = events.live.slice(0);2892 2893   for ( j = 0; j < live.length; j++ ) {2894     handleObj = live[j];2895 2896     if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {2897       selectors.push( handleObj.selector );2898 2899     } else {2900       live.splice( j--, 1 );2901     }2902   }2903 2904   match = jQuery( event.target ).closest( selectors, event.currentTarget );2905 2906   for ( i = 0, l = match.length; i < l; i++ ) {2907     close = match[i];2908 2909     for ( j = 0; j < live.length; j++ ) {2910       handleObj = live[j];2911 2912       if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {2913         elem = close.elem;2914         related = null;2915 2916         // Those two events require additional checking2917         if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {2918           event.type = handleObj.preType;2919           related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];2920         }2921 2922         if ( !related || related !== elem ) {2923           elems.push({ elem: elem, handleObj: handleObj, level: close.level });2924         }2925       }2926     }2927   }2928 2929   for ( i = 0, l = elems.length; i < l; i++ ) {2930     match = elems[i];2931 2932     if ( maxLevel && match.level > maxLevel ) {2933       break;2934     }2935 2936     event.currentTarget = match.elem;2937     event.data = match.handleObj.data;2938     event.handleObj = match.handleObj;2939 2940     ret = match.handleObj.origHandler.apply( match.elem, arguments );2941 2942     if ( ret === false || event.isPropagationStopped() ) {2943       maxLevel = match.level;2944 2945       if ( ret === false ) {2946         stop = false;2947       }2948       if ( event.isImmediatePropagationStopped() ) {2949         break;2950       }2951     }2952   }2953 2954   return stop;2955 }2956 2957 function liveConvert( type, selector ) {2958   return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");2959 }2960 2961 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +2962   "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +2963   "change select submit keydown keypress keyup error").split(" "), function( i, name ) {2964 2965   // Handle event binding2966   jQuery.fn[ name ] = function( data, fn ) {2967     if ( fn == null ) {2968       fn = data;2969       data = null;2970     }2971 2972     return arguments.length > 0 ?2973       this.bind( name, data, fn ) :2974       this.trigger( name );2975   };2976 2977   if ( jQuery.attrFn ) {2978     jQuery.attrFn[ name ] = true;2979   }2980 });2981 2982 // Prevent memory leaks in IE2983 // Window isn't included so as not to unbind existing unload events2984 // More info:2985 // - http://isaacschlueter.com/2006/10/msie-memory-leaks/2986 if ( window.attachEvent && !window.addEventListener ) {2987   jQuery(window).bind("unload", function() {2988     for ( var id in jQuery.cache ) {2989       if ( jQuery.cache[ id ].handle ) {2990         // Try/Catch is to handle iframes being unloaded, see #42802991         try {2992           jQuery.event.remove( jQuery.cache[ id ].handle.elem );2993         } catch(e) {}2994       }2995     }2996   });2997 }2998 2999 3000 /*!3001  * Sizzle CSS Selector Engine - v1.03002  * Copyright 2009, The Dojo Foundation3003  * Released under the MIT, BSD, and GPL Licenses.3004  * More information: http://sizzlejs.com/3005 */3006 (function(){3007 3008 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,3009   done = 0,3010   toString = Object.prototype.toString,3011   hasDuplicate = false,3012   baseHasDuplicate = true;3013 3014 // Here we check if the JavaScript engine is using some sort of3015 // optimization where it does not always call our comparision3016 // function. If that is the case, discard the hasDuplicate value.3017 //  Thus far that includes Google Chrome.3018 [0, 0].sort(function() {3019   baseHasDuplicate = false;3020   return 0;3021 });3022 3023 var Sizzle = function( selector, context, results, seed ) {3024   results = results || [];3025   context = context || document;3026 3027   var origContext = context;3028 3029   if ( context.nodeType !== 1 && context.nodeType !== 9 ) {3030     return [];3031   }3032   3033   if ( !selector || typeof selector !== "string" ) {3034     return results;3035   }3036 3037   var m, set, checkSet, extra, ret, cur, pop, i,3038     prune = true,3039     context Sizzle.is3040     parts = [],3041     soFar = selector;3042   3043   // Reset the position of the chunker regexp (start from head)3044   do {3045     chunker.exec( "" );3046     m = chunker.exec( soFar );3047 3048     if ( m ) {3049       soFar = m[3];3050     3051       parts.push( m[1] );3052     3053       if ( m[2] ) {3054         extra = m[3];3055         break;3056       }3057     }3058   } while ( m );3059 3060   if ( parts.length > 1 && origPOS.exec( selector ) ) {3061 3062     if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {3063       set = posProcess( parts[0] + parts[1], context );3064 3065     } else {3066       set = Expr.relative[ parts[0] ] ?3067         [ context ] :3068         Sizzle( parts.shift(), context );3069 3070       while ( parts.length ) {3071         selector = parts.shift();3072 3073         if ( Expr.relative[ selector ] ) {3074           selector += parts.shift();3075         }3076         3077         set = posProcess( selector, set );3078       }3079     }3080 3081   } else {3082     // Take a shortcut and set the context if the root selector is an ID3083     // (but not if it'll be faster if the inner selector is an ID)3084     if ( !seed && parts.length > 1 && context.nodeType === 9 && !context3085         Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {3086 3087       ret = Sizzle.find( parts.shift(), context, context3088       context = ret.expr ?3089         Sizzle.filter( ret.expr, ret.set )[0] :3090         ret.set[0];3091     }3092 3093     if ( context ) {3094       ret = seed ?3095         { expr: parts.pop(), set: makeArray(seed) } :3096         Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, context3097 3098       set = ret.expr ?3099         Sizzle.filter( ret.expr, ret.set ) :3100         ret.set;3101 3102       if ( parts.length > 0 ) {3103         checkSet = makeArray( set );3104 3105       } else {3106         prune = false;3107       }3108 3109       while ( parts.length ) {3110         cur = parts.pop();3111         pop = cur;3112 3113         if ( !Expr.relative[ cur ] ) {3114           cur = "";3115         } else {3116           pop = parts.pop();3117         }3118 3119         if ( pop == null ) {3120           pop = context;3121         }3122 3123         Expr.relative[ cur ]( checkSet, pop, context3124       }3125 3126     } else {3127       checkSet = parts = [];3128     }3129   }3130 3131   if ( !checkSet ) {3132     checkSet = set;3133   }3134 3135   if ( !checkSet ) {3136     Sizzle.error( cur || selector );3137   }3138 3139   if ( toString.call(checkSet) === "[object Array]" ) {3140     if ( !prune ) {3141       results.push.apply( results, checkSet );3142 3143     } else if ( context && context.nodeType === 1 ) {3144       for ( i = 0; checkSet[i] != null; i++ ) {3145         if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {3146           results.push( set[i] );3147         }3148       }3149 3150     } else {3151       for ( i = 0; checkSet[i] != null; i++ ) {3152         if ( checkSet[i] && checkSet[i].nodeType === 1 ) {3153           results.push( set[i] );3154         }3155       }3156     }3157 3158   } else {3159     makeArray( checkSet, results );3160   }3161 3162   if ( extra ) {3163     Sizzle( extra, origContext, results, seed );3164     Sizzle.uniqueSort( results );3165   }3166 3167   return results;3168 };3169 3170 Sizzle.uniqueSort = function( results ) {3171   if ( sortOrder ) {3172     hasDuplicate = baseHasDuplicate;3173     results.sort( sortOrder );3174 3175     if ( hasDuplicate ) {3176       for ( var i = 1; i < results.length; i++ ) {3177         if ( results[i] === results[ i - 1 ] ) {3178           results.splice( i--, 1 );3179         }3180       }3181     }3182   }3183 3184   return results;3185 };3186 3187 Sizzle.matches = function( expr, set ) {3188   return Sizzle( expr, null, null, set );3189 };3190 3191 Sizzle.matchesSelector = function( node, expr ) {3192   return Sizzle( expr, null, null, [node] ).length > 0;3193 };3194 3195 Sizzle.find = function( expr, context, is3196   var set;3197 3198   if ( !expr ) {3199     return [];3200   }3201 3202   for ( var i = 0, l = Expr.order.length; i < l; i++ ) {3203     var match,3204       type = Expr.order[i];3205     3206     if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {3207       var left = match[1];3208       match.splice( 1, 1 );3209 3210       if ( left.substr( left.length - 1 ) !== "\\" ) {3211         match[1] = (match[1] || "").replace(/\\/g, "");3212         set = Expr.find[ type ]( match, context, is3213 3214         if ( set != null ) {3215           expr = expr.replace( Expr.match[ type ], "" );3216           break;3217         }3218       }3219     }3220   }3221 3222   if ( !set ) {3223     set = context.getElementsByTagName( "*" );3224   }3225 3226   return { set: set, expr: expr };3227 };3228 3229 Sizzle.filter = function( expr, set, inplace, not ) {3230   var match, anyFound,3231     old = expr,3232     result = [],3233     curLoop = set,3234     is] );3235 3236   while ( expr && set.length ) {3237     for ( var type in Expr.filter ) {3238       if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {3239         var found, item,3240           filter = Expr.filter[ type ],3241           left = match[1];3242 3243         anyFound = false;3244 3245         match.splice(1,1);3246 3247         if ( left.substr( left.length - 1 ) === "\\" ) {3248           continue;3249         }3250 3251         if ( curLoop === result ) {3252           result = [];3253         }3254 3255         if ( Expr.preFilter[ type ] ) {3256           match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, is3257 3258           if ( !match ) {3259             anyFound = found = true;3260 3261           } else if ( match === true ) {3262             continue;3263           }3264         }3265 3266         if ( match ) {3267           for ( var i = 0; (item = curLoop[i]) != null; i++ ) {3268             if ( item ) {3269               found = filter( item, match, i, curLoop );3270               var pass = not ^ !!found;3271 3272               if ( inplace && found != null ) {3273                 if ( pass ) {3274                   anyFound = true;3275 3276                 } else {3277                   curLoop[i] = false;3278                 }3279 3280               } else if ( pass ) {3281                 result.push( item );3282                 anyFound = true;3283               }3284             }3285           }3286         }3287 3288         if ( found !== undefined ) {3289           if ( !inplace ) {3290             curLoop = result;3291           }3292 3293           expr = expr.replace( Expr.match[ type ], "" );3294 3295           if ( !anyFound ) {3296             return [];3297           }3298 3299           break;3300         }3301       }3302     }3303 3304     // Improper expression3305     if ( expr === old ) {3306       if ( anyFound == null ) {3307         Sizzle.error( expr );3308 3309       } else {3310         break;3311       }3312     }3313 3314     old = expr;3315   }3316 3317   return curLoop;3318 };3319 3320 Sizzle.error = function( msg ) {3321   throw "Syntax error, unrecognized expression: " + msg;3322 };3323 3324 var Expr = Sizzle.selectors = {3325   order: [ "ID", "NAME", "TAG" ],3326 3327   match: {3328     ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,3329     CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,3330     NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,3331     ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,3332     TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,3333     CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,3334     POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,3335     PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/3336   },3337 3338   leftMatch: {},3339 3340   attrMap: {3341     "class": "className",3342     "for": "htmlFor"3343   },3344 3345   attrHandle: {3346     href: function( elem ) {3347       return elem.getAttribute( "href" );3348     }3349   },3350 3351   relative: {3352     "+": function(checkSet, part){3353       var isPartStr = typeof part === "string",3354         isTag = isPartStr && !/\W/.test( part ),3355         isPartStrNotTag = isPartStr && !isTag;3356 3357       if ( isTag ) {3358         part = part.toLowerCase();3359       }3360 3361       for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {3362         if ( (elem = checkSet[i]) ) {3363           while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}3364 3365           checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?3366             elem || false :3367             elem === part;3368         }3369       }3370 3371       if ( isPartStrNotTag ) {3372         Sizzle.filter( part, checkSet, true );3373       }3374     },3375 3376     ">": function( checkSet, part ) {3377       var elem,3378         isPartStr = typeof part === "string",3379         i = 0,3380         l = checkSet.length;3381 3382       if ( isPartStr && !/\W/.test( part ) ) {3383         part = part.toLowerCase();3384 3385         for ( ; i < l; i++ ) {3386           elem = checkSet[i];3387 3388           if ( elem ) {3389             var parent = elem.parentNode;3390             checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;3391           }3392         }3393 3394       } else {3395         for ( ; i < l; i++ ) {3396           elem = checkSet[i];3397 3398           if ( elem ) {3399             checkSet[i] = isPartStr ?3400               elem.parentNode :3401               elem.parentNode === part;3402           }3403         }3404 3405         if ( isPartStr ) {3406           Sizzle.filter( part, checkSet, true );3407         }3408       }3409     },3410 3411     "": function(checkSet, part, is3412       var nodeCheck,3413         doneName = done++,3414         checkFn = dirCheck;3415 3416       if ( typeof part === "string" && !/\W/.test(part) ) {3417         part = part.toLowerCase();3418         nodeCheck = part;3419         checkFn = dirNodeCheck;3420       }3421 3422       checkFn( "parentNode", part, doneName, checkSet, nodeCheck, is3423     },3424 3425     "~": function( checkSet, part, is3426       var nodeCheck,3427         doneName = done++,3428         checkFn = dirCheck;3429 3430       if ( typeof part === "string" && !/\W/.test( part ) ) {3431         part = part.toLowerCase();3432         nodeCheck = part;3433         checkFn = dirNodeCheck;3434       }3435 3436       checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, is3437     }3438   },3439 3440   find: {3441     ID: function( match, context, is3442       if ( typeof context.getElementById !== "undefined" && !is3443         var m = context.getElementById(match[1]);3444         // Check parentNode to catch when Blackberry 4.6 returns3445         // nodes that are no longer in the document #69633446         return m && m.parentNode ? [m] : [];3447       }3448     },3449 3450     NAME: function( match, context ) {3451       if ( typeof context.getElementsByName !== "undefined" ) {3452         var ret = [],3453           results = context.getElementsByName( match[1] );3454 3455         for ( var i = 0, l = results.length; i < l; i++ ) {3456           if ( results[i].getAttribute("name") === match[1] ) {3457             ret.push( results[i] );3458           }3459         }3460 3461         return ret.length === 0 ? null : ret;3462       }3463     },3464 3465     TAG: function( match, context ) {3466       return context.getElementsByTagName( match[1] );3467     }3468   },3469   preFilter: {3470     CLASS: function( match, curLoop, inplace, result, not, is3471       match = " " + match[1].replace(/\\/g, "") + " ";3472 3473       if ( is3474         return match;3475       }3476 3477       for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {3478         if ( elem ) {3479           if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {3480             if ( !inplace ) {3481               result.push( elem );3482             }3483 3484           } else if ( inplace ) {3485             curLoop[i] = false;3486           }3487         }3488       }3489 3490       return false;3491     },3492 3493     ID: function( match ) {3494       return match[1].replace(/\\/g, "");3495     },3496 3497     TAG: function( match, curLoop ) {3498       return match[1].toLowerCase();3499     },3500 3501     CHILD: function( match ) {3502       if ( match[1] === "nth" ) {3503         // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'3504         var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(3505           match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||3506           !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);3507 3508         // calculate the numbers (first)n+(last) including if they are negative3509         match[2] = (test[1] + (test[2] || 1)) - 0;3510         match[3] = test[3] - 0;3511       }3512 3513       // TODO: Move to normal caching system3514       match[0] = done++;3515 3516       return match;3517     },3518 3519     ATTR: function( match, curLoop, inplace, result, not, is3520       var name = match[1].replace(/\\/g, "");3521       3522       if ( !is Expr.attrMap[name] ) {3523         match[1] = Expr.attrMap[name];3524       }3525 3526       if ( match[2] === "~=" ) {3527         match[4] = " " + match[4] + " ";3528       }3529 3530       return match;3531     },3532 3533     PSEUDO: function( match, curLoop, inplace, result, not ) {3534       if ( match[1] === "not" ) {3535         // If we're dealing with a complex expression, or a simple one3536         if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {3537           match[3] = Sizzle(match[3], null, null, curLoop);3538 3539         } else {3540           var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);3541 3542           if ( !inplace ) {3543             result.push.apply( result, ret );3544           }3545 3546           return false;3547         }3548 3549       } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {3550         return true;3551       }3552       3553       return match;3554     },3555 3556     POS: function( match ) {3557       match.unshift( true );3558 3559       return match;3560     }3561   },3562   3563   filters: {3564     enabled: function( elem ) {3565       return elem.disabled === false && elem.type !== "hidden";3566     },3567 3568     disabled: function( elem ) {3569       return elem.disabled === true;3570     },3571 3572     checked: function( elem ) {3573       return elem.checked === true;3574     },3575     3576     selected: function( elem ) {3577       // Accessing this property makes selected-by-default3578       // options in Safari work properly3579       elem.parentNode.selectedIndex;3580       3581       return elem.selected === true;3582     },3583 3584     parent: function( elem ) {3585       return !!elem.firstChild;3586     },3587 3588     empty: function( elem ) {3589       return !elem.firstChild;3590     },3591 3592     has: function( elem, i, match ) {3593       return !!Sizzle( match[3], elem ).length;3594     },3595 3596     header: function( elem ) {3597       return (/h\d/i).test( elem.nodeName );3598     },3599 3600     text: function( elem ) {3601       return "text" === elem.type;3602     },3603     radio: function( elem ) {3604       return "radio" === elem.type;3605     },3606 3607     checkbox: function( elem ) {3608       return "checkbox" === elem.type;3609     },3610 3611     file: function( elem ) {3612       return "file" === elem.type;3613     },3614     password: function( elem ) {3615       return "password" === elem.type;3616     },3617 3618     submit: function( elem ) {3619       return "submit" === elem.type;3620     },3621 3622     image: function( elem ) {3623       return "image" === elem.type;3624     },3625 3626     reset: function( elem ) {3627       return "reset" === elem.type;3628     },3629 3630     button: function( elem ) {3631       return "button" === elem.type || elem.nodeName.toLowerCase() === "button";3632     },3633 3634     input: function( elem ) {3635       return (/input|select|textarea|button/i).test( elem.nodeName );3636     }3637   },3638   setFilters: {3639     first: function( elem, i ) {3640       return i === 0;3641     },3642 3643     last: function( elem, i, match, array ) {3644       return i === array.length - 1;3645     },3646 3647     even: function( elem, i ) {3648       return i % 2 === 0;3649     },3650 3651     odd: function( elem, i ) {3652       return i % 2 === 1;3653     },3654 3655     lt: function( elem, i, match ) {3656       return i < match[3] - 0;3657     },3658 3659     gt: function( elem, i, match ) {3660       return i > match[3] - 0;3661     },3662 3663     nth: function( elem, i, match ) {3664       return match[3] - 0 === i;3665     },3666 3667     eq: function( elem, i, match ) {3668       return match[3] - 0 === i;3669     }3670   },3671   filter: {3672     PSEUDO: function( elem, match, i, array ) {3673       var name = match[1],3674         filter = Expr.filters[ name ];3675 3676       if ( filter ) {3677         return filter( elem, i, match, array );3678 3679       } else if ( name === "contains" ) {3680         return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;3681 3682       } else if ( name === "not" ) {3683         var not = match[3];3684 3685         for ( var j = 0, l = not.length; j < l; j++ ) {3686           if ( not[j] === elem ) {3687             return false;3688           }3689         }3690 3691         return true;3692 3693       } else {3694         Sizzle.error( "Syntax error, unrecognized expression: " + name );3695       }3696     },3697 3698     CHILD: function( elem, match ) {3699       var type = match[1],3700         node = elem;3701 3702       switch ( type ) {3703         case "only":3704         case "first":3705           while ( (node = node.previousSibling) )   {3706             if ( node.nodeType === 1 ) { 3707               return false; 3708             }3709           }3710 3711           if ( type === "first" ) { 3712             return true; 3713           }3714 3715           node = elem;3716 3717         case "last":3718           while ( (node = node.nextSibling) )   {3719             if ( node.nodeType === 1 ) { 3720               return false; 3721             }3722           }3723 3724           return true;3725 3726         case "nth":3727           var first = match[2],3728             last = match[3];3729 3730           if ( first === 1 && last === 0 ) {3731             return true;3732           }3733           3734           var doneName = match[0],3735             parent = elem.parentNode;3736   3737           if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {3738             var count = 0;3739             3740             for ( node = parent.firstChild; node; node = node.nextSibling ) {3741               if ( node.nodeType === 1 ) {3742                 node.nodeIndex = ++count;3743               }3744             } 3745 3746             parent.sizcache = doneName;3747           }3748           3749           var diff = elem.nodeIndex - last;3750 3751           if ( first === 0 ) {3752             return diff === 0;3753 3754           } else {3755             return ( diff % first === 0 && diff / first >= 0 );3756           }3757       }3758     },3759 3760     ID: function( elem, match ) {3761       return elem.nodeType === 1 && elem.getAttribute("id") === match;3762     },3763 3764     TAG: function( elem, match ) {3765       return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;3766     },3767     3768     CLASS: function( elem, match ) {3769       return (" " + (elem.className || elem.getAttribute("class")) + " ")3770         .indexOf( match ) > -1;3771     },3772 3773     ATTR: function( elem, match ) {3774       var name = match[1],3775         result = Expr.attrHandle[ name ] ?3776           Expr.attrHandle[ name ]( elem ) :3777           elem[ name ] != null ?3778             elem[ name ] :3779             elem.getAttribute( name ),3780         value = result + "",3781         type = match[2],3782         check = match[4];3783 3784       return result == null ?3785         type === "!=" :3786         type === "=" ?3787         value === check :3788         type === "*=" ?3789         value.indexOf(check) >= 0 :3790         type === "~=" ?3791         (" " + value + " ").indexOf(check) >= 0 :3792         !check ?3793         value && result !== false :3794         type === "!=" ?3795         value !== check :3796         type === "^=" ?3797         value.indexOf(check) === 0 :3798         type === "$=" ?3799         value.substr(value.length - check.length) === check :3800         type === "|=" ?3801         value === check || value.substr(0, check.length + 1) === check + "-" :3802         false;3803     },3804 3805     POS: function( elem, match, i, array ) {3806       var name = match[2],3807         filter = Expr.setFilters[ name ];3808 3809       if ( filter ) {3810         return filter( elem, i, match, array );3811       }3812     }3813   }3814 };3815 3816 var origPOS = Expr.match.POS,3817   fescape = function(all, num){3818     return "\\" + (num - 0 + 1);3819   };3820 3821 for ( var type in Expr.match ) {3822   Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );3823   Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );3824 }3825 3826 var makeArray = function( array, results ) {3827   array = Array.prototype.slice.call( array, 0 );3828 3829   if ( results ) {3830     results.push.apply( results, array );3831     return results;3832   }3833   3834   return array;3835 };3836 3837 // Perform a simple check to determine if the browser is capable of3838 // converting a NodeList to an array using builtin methods.3839 // Also verifies that the returned array holds DOM nodes3840 // (which is not the case in the Blackberry browser)3841 try {3842   Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;3843 3844 // Provide a fallback method if it does not work3845 } catch( e ) {3846   makeArray = function( array, results ) {3847     var i = 0,3848       ret = results || [];3849 3850     if ( toString.call(array) === "[object Array]" ) {3851       Array.prototype.push.apply( ret, array );3852 3853     } else {3854       if ( typeof array.length === "number" ) {3855         for ( var l = array.length; i < l; i++ ) {3856           ret.push( array[i] );3857         }3858 3859       } else {3860         for ( ; array[i]; i++ ) {3861           ret.push( array[i] );3862         }3863       }3864     }3865 3866     return ret;3867   };3868 }3869 3870 var sortOrder, siblingCheck;3871 3872 if ( document.documentElement.compareDocumentPosition ) {3873   sortOrder = function( a, b ) {3874     if ( a === b ) {3875       hasDuplicate = true;3876       return 0;3877     }3878 3879     if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {3880       return a.compareDocumentPosition ? -1 : 1;3881     }3882 3883     return a.compareDocumentPosition(b) & 4 ? -1 : 1;3884   };3885 3886 } else {3887   sortOrder = function( a, b ) {3888     var al, bl,3889       ap = [],3890       bp = [],3891       aup = a.parentNode,3892       bup = b.parentNode,3893       cur = aup;3894 3895     // The nodes are identical, we can exit early3896     if ( a === b ) {3897       hasDuplicate = true;3898       return 0;3899 3900     // If the nodes are siblings (or identical) we can do a quick check3901     } else if ( aup === bup ) {3902       return siblingCheck( a, b );3903 3904     // If no parents were found then the nodes are disconnected3905     } else if ( !aup ) {3906       return -1;3907 3908     } else if ( !bup ) {3909       return 1;3910     }3911 3912     // Otherwise they're somewhere else in the tree so we need3913     // to build up a full list of the parentNodes for comparison3914     while ( cur ) {3915       ap.unshift( cur );3916       cur = cur.parentNode;3917     }3918 3919     cur = bup;3920 3921     while ( cur ) {3922       bp.unshift( cur );3923       cur = cur.parentNode;3924     }3925 3926     al = ap.length;3927     bl = bp.length;3928 3929     // Start walking down the tree looking for a discrepancy3930     for ( var i = 0; i < al && i < bl; i++ ) {3931       if ( ap[i] !== bp[i] ) {3932         return siblingCheck( ap[i], bp[i] );3933       }3934     }3935 3936     // We ended someplace up the tree so do a sibling check3937     return i === al ?3938       siblingCheck( a, bp[i], -1 ) :3939       siblingCheck( ap[i], b, 1 );3940   };3941 3942   siblingCheck = function( a, b, ret ) {3943     if ( a === b ) {3944       return ret;3945     }3946 3947     var cur = a.nextSibling;3948 3949     while ( cur ) {3950       if ( cur === b ) {3951         return -1;3952       }3953 3954       cur = cur.nextSibling;3955     }3956 3957     return 1;3958   };3959 }3960 3961 // Utility function for retreiving the text value of an array of DOM nodes3962 Sizzle.getText = function( elems ) {3963   var ret = "", elem;3964 3965   for ( var i = 0; elems[i]; i++ ) {3966     elem = elems[i];3967 3968     // Get the text from text nodes and CDATA nodes3969     if ( elem.nodeType === 3 || elem.nodeType === 4 ) {3970       ret += elem.nodeValue;3971 3972     // Traverse everything else, except comment nodes3973     } else if ( elem.nodeType !== 8 ) {3974       ret += Sizzle.getText( elem.childNodes );3975     }3976   }3977 3978   return ret;3979 };3980 3981 // Check to see if the browser returns elements by name when3982 // querying by getElementById (and provide a workaround)3983 (function(){3984   // We're going to inject a fake input element with a specified name3985   var form = document.createElement("div"),3986     id = "script" + (new Date()).getTime(),3987     root = document.documentElement;3988 3989   form.innerHTML = "<a name='" + id + "'/>";3990 3991   // Inject it into the root element, check its status, and remove it quickly3992   root.insertBefore( form, root.firstChild );3993 3994   // The workaround has to do additional checks after a getElementById3995   // Which slows things down for other browsers (hence the branching)3996   if ( document.getElementById( id ) ) {3997     Expr.find.ID = function( match, context, is3998       if ( typeof context.getElementById !== "undefined" && !is3999         var m = context.getElementById(match[1]);4000 4001         return m ?4002           m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?4003             [m] :4004             undefined :4005           [];4006       }4007     };4008 4009     Expr.filter.ID = function( elem, match ) {4010       var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");4011 4012       return elem.nodeType === 1 && node && node.nodeValue === match;4013     };4014   }4015 4016   root.removeChild( form );4017 4018   // release memory in IE4019   root = form = null;4020 })();4021 4022 (function(){4023   // Check to see if the browser returns only elements4024   // when doing getElementsByTagName("*")4025 4026   // Create a fake element4027   var div = document.createElement("div");4028   div.appendChild( document.createComment("") );4029 4030   // Make sure no comments are found4031   if ( div.getElementsByTagName("*").length > 0 ) {4032     Expr.find.TAG = function( match, context ) {4033       var results = context.getElementsByTagName( match[1] );4034 4035       // Filter out possible comments4036       if ( match[1] === "*" ) {4037         var tmp = [];4038 4039         for ( var i = 0; results[i]; i++ ) {4040           if ( results[i].nodeType === 1 ) {4041             tmp.push( results[i] );4042           }4043         }4044 4045         results = tmp;4046       }4047 4048       return results;4049     };4050   }4051 4052   // Check to see if an attribute returns normalized href attributes4053   div.innerHTML = "<a href='#'></a>";4054 4055   if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&4056       div.firstChild.getAttribute("href") !== "#" ) {4057 4058     Expr.attrHandle.href = function( elem ) {4059       return elem.getAttribute( "href", 2 );4060     };4061   }4062 4063   // release memory in IE4064   div = null;4065 })();4066 4067 if ( document.querySelectorAll ) {4068   (function(){4069     var oldSizzle = Sizzle,4070       div = document.createElement("div"),4071       id = "__sizzle__";4072 4073     div.innerHTML = "<p class='TEST'></p>";4074 4075     // Safari can't handle uppercase or unicode characters when4076     // in quirks mode.4077     if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {4078       return;4079     }4080   4081     Sizzle = function( query, context, extra, seed ) {4082       context = context || document;4083 4084       // Make sure that attribute selectors are quoted4085       query = query.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");4086 4087       // Only use querySelectorAll on non-4088       // (ID selectors don't work in non-HTML documents)4089       if ( !seed && !Sizzle.is4090         if ( context.nodeType === 9 ) {4091           try {4092             return makeArray( context.querySelectorAll(query), extra );4093           } catch(qsaError) {}4094 4095         // qSA works strangely on Element-rooted queries4096         // We can work around this by specifying an extra ID on the root4097         // and working up from there (Thanks to Andrew Dupont for the technique)4098         // IE 8 doesn't work on object elements4099         } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {4100           var old = context.getAttribute( "id" ),4101             nid = old || id;4102 4103           if ( !old ) {4104             context.setAttribute( "id", nid );4105           }4106 4107           try {4108             return makeArray( context.querySelectorAll( "#" + nid + " " + query ), extra );4109 4110           } catch(pseudoError) {4111           } finally {4112             if ( !old ) {4113               context.removeAttribute( "id" );4114             }4115           }4116         }4117       }4118     4119       return oldSizzle(query, context, extra, seed);4120     };4121 4122     for ( var prop in oldSizzle ) {4123       Sizzle[ prop ] = oldSizzle[ prop ];4124     }4125 4126     // release memory in IE4127     div = null;4128   })();4129 }4130 4131 (function(){4132   var html = document.documentElement,4133     matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector,4134     pseudoWorks = false;4135 4136   try {4137     // This should fail with an exception4138     // Gecko does not error, returns false instead4139     matches.call( document.documentElement, "[test!='']:sizzle" );4140   4141   } catch( pseudoError ) {4142     pseudoWorks = true;4143   }4144 4145   if ( matches ) {4146     Sizzle.matchesSelector = function( node, expr ) {4147       // Make sure that attribute selectors are quoted4148       expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");4149 4150       if ( !Sizzle.is4151         try { 4152           if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {4153             return matches.call( node, expr );4154           }4155         } catch(e) {}4156       }4157 4158       return Sizzle(expr, null, null, [node]).length > 0;4159     };4160   }4161 })();4162 4163 (function(){4164   var div = document.createElement("div");4165 4166   div.innerHTML = "<div class='test e'></div><div class='test'></div>";4167 4168   // Opera can't find a second classname (in 9.6)4169   // Also, make sure that getElementsByClassName actually exists4170   if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {4171     return;4172   }4173 4174   // Safari caches class attributes, doesn't catch changes (in 3.2)4175   div.lastChild.className = "e";4176 4177   if ( div.getElementsByClassName("e").length === 1 ) {4178     return;4179   }4180   4181   Expr.order.splice(1, 0, "CLASS");4182   Expr.find.CLASS = function( match, context, is4183     if ( typeof context.getElementsByClassName !== "undefined" && !is4184       return context.getElementsByClassName(match[1]);4185     }4186   };4187 4188   // release memory in IE4189   div = null;4190 })();4191 4192 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, is4193   for ( var i = 0, l = checkSet.length; i < l; i++ ) {4194     var elem = checkSet[i];4195 4196     if ( elem ) {4197       var match = false;4198 4199       elem = elem[dir];4200 4201       while ( elem ) {4202         if ( elem.sizcache === doneName ) {4203           match = checkSet[elem.sizset];4204           break;4205         }4206 4207         if ( elem.nodeType === 1 && !is4208           elem.sizcache = doneName;4209           elem.sizset = i;4210         }4211 4212         if ( elem.nodeName.toLowerCase() === cur ) {4213           match = elem;4214           break;4215         }4216 4217         elem = elem[dir];4218       }4219 4220       checkSet[i] = match;4221     }4222   }4223 }4224 4225 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, is4226   for ( var i = 0, l = checkSet.length; i < l; i++ ) {4227     var elem = checkSet[i];4228 4229     if ( elem ) {4230       var match = false;4231       4232       elem = elem[dir];4233 4234       while ( elem ) {4235         if ( elem.sizcache === doneName ) {4236           match = checkSet[elem.sizset];4237           break;4238         }4239 4240         if ( elem.nodeType === 1 ) {4241           if ( !is4242             elem.sizcache = doneName;4243             elem.sizset = i;4244           }4245 4246           if ( typeof cur !== "string" ) {4247             if ( elem === cur ) {4248               match = true;4249               break;4250             }4251 4252           } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {4253             match = elem;4254             break;4255           }4256         }4257 4258         elem = elem[dir];4259       }4260 4261       checkSet[i] = match;4262     }4263   }4264 }4265 4266 if ( document.documentElement.contains ) {4267   Sizzle.contains = function( a, b ) {4268     return a !== b && (a.contains ? a.contains(b) : true);4269   };4270 4271 } else if ( document.documentElement.compareDocumentPosition ) {4272   Sizzle.contains = function( a, b ) {4273     return !!(a.compareDocumentPosition(b) & 16);4274   };4275 4276 } else {4277   Sizzle.contains = function() {4278     return false;4279   };4280 }4281 4282 Sizzle.isfunction( elem ) {4283   // documentElement is verified for cases where it doesn't yet exist4284   // (such as loading iframes in IE - #4833) 4285   var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;4286 4287   return documentElement ? documentElement.nodeName !== "HTML" : false;4288 };4289 4290 var posProcess = function( selector, context ) {4291   var match,4292     tmpSet = [],4293     later = "",4294     root = context.nodeType ? [context] : context;4295 4296   // Position selectors must be done after the filter4297   // And so must :not(positional) so we move all PSEUDOs to the end4298   while ( (match = Expr.match.PSEUDO.exec( selector )) ) {4299     later += match[0];4300     selector = selector.replace( Expr.match.PSEUDO, "" );4301   }4302 4303   selector = Expr.relative[selector] ? selector + "*" : selector;4304 4305   for ( var i = 0, l = root.length; i < l; i++ ) {4306     Sizzle( selector, root[i], tmpSet );4307   }4308 4309   return Sizzle.filter( later, tmpSet );4310 };4311 4312 // EXPOSE4313 jQuery.find = Sizzle;4314 jQuery.expr = Sizzle.selectors;4315 jQuery.expr[":"] = jQuery.expr.filters;4316 jQuery.unique = Sizzle.uniqueSort;4317 jQuery.text = Sizzle.getText;4318 jQuery.is Sizzle.is4319 jQuery.contains = Sizzle.contains;4320 4321 4322 })();4323 4324 4325 var runtil = /Until$/,4326   rparentsprev = /^(?:parents|prevUntil|prevAll)/,4327   // Note: This RegExp should be improved, or likely pulled from Sizzle4328   rmultiselector = /,/,4329   isSimple = /^.[^:#\[\.,]*$/,4330   slice = Array.prototype.slice,4331   POS = jQuery.expr.match.POS;4332 4333 jQuery.fn.extend({4334   find: function( selector ) {4335     var ret = this.pushStack( "", "find", selector ),4336       length = 0;4337 4338     for ( var i = 0, l = this.length; i < l; i++ ) {4339       length = ret.length;4340       jQuery.find( selector, this[i], ret );4341 4342       if ( i > 0 ) {4343         // Make sure that the results are unique4344         for ( var n = length; n < ret.length; n++ ) {4345           for ( var r = 0; r < length; r++ ) {4346             if ( ret[r] === ret[n] ) {4347               ret.splice(n--, 1);4348               break;4349             }4350           }4351         }4352       }4353     }4354 4355     return ret;4356   },4357 4358   has: function( target ) {4359     var targets = jQuery( target );4360     return this.filter(function() {4361       for ( var i = 0, l = targets.length; i < l; i++ ) {4362         if ( jQuery.contains( this, targets[i] ) ) {4363           return true;4364         }4365       }4366     });4367   },4368 4369   not: function( selector ) {4370     return this.pushStack( winnow(this, selector, false), "not", selector);4371   },4372 4373   filter: function( selector ) {4374     return this.pushStack( winnow(this, selector, true), "filter", selector );4375   },4376   4377   is: function( selector ) {4378     return !!selector && jQuery.filter( selector, this ).length > 0;4379   },4380 4381   closest: function( selectors, context ) {4382     var ret = [], i, l, cur = this[0];4383 4384     if ( jQuery.isArray( selectors ) ) {4385       var match, selector,4386         matches = {},4387         level = 1;4388 4389       if ( cur && selectors.length ) {4390         for ( i = 0, l = selectors.length; i < l; i++ ) {4391           selector = selectors[i];4392 4393           if ( !matches[selector] ) {4394             matches[selector] = jQuery.expr.match.POS.test( selector ) ? 4395               jQuery( selector, context || this.context ) :4396               selector;4397           }4398         }4399 4400         while ( cur && cur.ownerDocument && cur !== context ) {4401           for ( selector in matches ) {4402             match = matches[selector];4403 4404             if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {4405               ret.push({ selector: selector, elem: cur, level: level });4406             }4407           }4408 4409           cur = cur.parentNode;4410           level++;4411         }4412       }4413 4414       return ret;4415     }4416 4417     var pos = POS.test( selectors ) ? 4418       jQuery( selectors, context || this.context ) : null;4419 4420     for ( i = 0, l = this.length; i < l; i++ ) {4421       cur = this[i];4422 4423       while ( cur ) {4424         if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {4425           ret.push( cur );4426           break;4427 4428         } else {4429           cur = cur.parentNode;4430           if ( !cur || !cur.ownerDocument || cur === context ) {4431             break;4432           }4433         }4434       }4435     }4436 4437     ret = ret.length > 1 ? jQuery.unique(ret) : ret;4438     4439     return this.pushStack( ret, "closest", selectors );4440   },4441   4442   // Determine the position of an element within4443   // the matched set of elements4444   index: function( elem ) {4445     if ( !elem || typeof elem === "string" ) {4446       return jQuery.inArray( this[0],4447         // If it receives a string, the selector is used4448         // If it receives nothing, the siblings are used4449         elem ? jQuery( elem ) : this.parent().children() );4450     }4451     // Locate the position of the desired element4452     return jQuery.inArray(4453       // If it receives a jQuery object, the first element is used4454       elem.jquery ? elem[0] : elem, this );4455   },4456 4457   add: function( selector, context ) {4458     var set = typeof selector === "string" ?4459         jQuery( selector, context || this.context ) :4460         jQuery.makeArray( selector ),4461       all = jQuery.merge( this.get(), set );4462 4463     return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?4464       all :4465       jQuery.unique( all ) );4466   },4467 4468   andSelf: function() {4469     return this.add( this.prevObject );4470   }4471 });4472 4473 // A painfully simple check to see if an element is disconnected4474 // from a document (should be improved, where feasible).4475 function isDisconnected( node ) {4476   return !node || !node.parentNode || node.parentNode.nodeType === 11;4477 }4478 4479 jQuery.each({4480   parent: function( elem ) {4481     var parent = elem.parentNode;4482     return parent && parent.nodeType !== 11 ? parent : null;4483   },4484   parents: function( elem ) {4485     return jQuery.dir( elem, "parentNode" );4486   },4487   parentsUntil: function( elem, i, until ) {4488     return jQuery.dir( elem, "parentNode", until );4489   },4490   next: function( elem ) {4491     return jQuery.nth( elem, 2, "nextSibling" );4492   },4493   prev: function( elem ) {4494     return jQuery.nth( elem, 2, "previousSibling" );4495   },4496   nextAll: function( elem ) {4497     return jQuery.dir( elem, "nextSibling" );4498   },4499   prevAll: function( elem ) {4500     return jQuery.dir( elem, "previousSibling" );4501   },4502   nextUntil: function( elem, i, until ) {4503     return jQuery.dir( elem, "nextSibling", until );4504   },4505   prevUntil: function( elem, i, until ) {4506     return jQuery.dir( elem, "previousSibling", until );4507   },4508   siblings: function( elem ) {4509     return jQuery.sibling( elem.parentNode.firstChild, elem );4510   },4511   children: function( elem ) {4512     return jQuery.sibling( elem.firstChild );4513   },4514   contents: function( elem ) {4515     return jQuery.nodeName( elem, "iframe" ) ?4516       elem.contentDocument || elem.contentWindow.document :4517       jQuery.makeArray( elem.childNodes );4518   }4519 }, function( name, fn ) {4520   jQuery.fn[ name ] = function( until, selector ) {4521     var ret = jQuery.map( this, fn, until );4522     4523     if ( !runtil.test( name ) ) {4524       selector = until;4525     }4526 4527     if ( selector && typeof selector === "string" ) {4528       ret = jQuery.filter( selector, ret );4529     }4530 4531     ret = this.length > 1 ? jQuery.unique( ret ) : ret;4532 4533     if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {4534       ret = ret.reverse();4535     }4536 4537     return this.pushStack( ret, name, slice.call(arguments).join(",") );4538   };4539 });4540 4541 jQuery.extend({4542   filter: function( expr, elems, not ) {4543     if ( not ) {4544       expr = ":not(" + expr + ")";4545     }4546 4547     return elems.length === 1 ?4548       jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :4549       jQuery.find.matches(expr, elems);4550   },4551   4552   dir: function( elem, dir, until ) {4553     var matched = [],4554       cur = elem[ dir ];4555 4556     while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {4557       if ( cur.nodeType === 1 ) {4558         matched.push( cur );4559       }4560       cur = cur[dir];4561     }4562     return matched;4563   },4564 4565   nth: function( cur, result, dir, elem ) {4566     result = result || 1;4567     var num = 0;4568 4569     for ( ; cur; cur = cur[dir] ) {4570       if ( cur.nodeType === 1 && ++num === result ) {4571         break;4572       }4573     }4574 4575     return cur;4576   },4577 4578   sibling: function( n, elem ) {4579     var r = [];4580 4581     for ( ; n; n = n.nextSibling ) {4582       if ( n.nodeType === 1 && n !== elem ) {4583         r.push( n );4584       }4585     }4586 4587     return r;4588   }4589 });4590 4591 // Implement the identical functionality for filter and not4592 function winnow( elements, qualifier, keep ) {4593   if ( jQuery.isFunction( qualifier ) ) {4594     return jQuery.grep(elements, function( elem, i ) {4595       var retVal = !!qualifier.call( elem, i, elem );4596       return retVal === keep;4597     });4598 4599   } else if ( qualifier.nodeType ) {4600     return jQuery.grep(elements, function( elem, i ) {4601       return (elem === qualifier) === keep;4602     });4603 4604   } else if ( typeof qualifier === "string" ) {4605     var filtered = jQuery.grep(elements, function( elem ) {4606       return elem.nodeType === 1;4607     });4608 4609     if ( isSimple.test( qualifier ) ) {4610       return jQuery.filter(qualifier, filtered, !keep);4611     } else {4612       qualifier = jQuery.filter( qualifier, filtered );4613     }4614   }4615 4616   return jQuery.grep(elements, function( elem, i ) {4617     return (jQuery.inArray( elem, qualifier ) >= 0) === keep;4618   });4619 }4620 4621 4622 4623 4624 var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,4625   rleadingWhitespace = /^\s+/,4626   rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,4627   rtagName = /<([\w:]+)/,4628   rtbody = /<tbody/i,4629   rhtml = /<|&#?\w+;/,4630   rnocache = /<(?:script|object|embed|option|style)/i,4631   // checked="checked" or checked (html5)4632   rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,4633   raction = /\=([^="'>\s]+\/)>/g,4634   wrapMap = {4635     option: [ 1, "<select multiple='multiple'>", "</select>" ],4636     legend: [ 1, "<fieldset>", "</fieldset>" ],4637     thead: [ 1, "<table>", "</table>" ],4638     tr: [ 2, "<table><tbody>", "</tbody></table>" ],4639     td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],4640     col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],4641     area: [ 1, "<map>", "</map>" ],4642     _default: [ 0, "", "" ]4643   };4644 4645 wrapMap.optgroup = wrapMap.option;4646 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;4647 wrapMap.th = wrapMap.td;4648 4649 // IE can't serialize <link> and <script> tags normally4650 if ( !jQuery.support.htmlSerialize ) {4651   wrapMap._default = [ 1, "div<div>", "</div>" ];4652 }4653 4654 jQuery.fn.extend({4655   text: function( text ) {4656     if ( jQuery.isFunction(text) ) {4657       return this.each(function(i) {4658         var self = jQuery( this );4659 4660         self.text( text.call(this, i, self.text()) );4661       });4662     }4663 4664     if ( typeof text !== "object" && text !== undefined ) {4665       return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );4666     }4667 4668     return jQuery.text( this );4669   },4670 4671   wrapAll: function( html ) {4672     if ( jQuery.isFunction( html ) ) {4673       return this.each(function(i) {4674         jQuery(this).wrapAll( html.call(this, i) );4675       });4676     }4677 4678     if ( this[0] ) {4679       // The elements to wrap the target around4680       var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);4681 4682       if ( this[0].parentNode ) {4683         wrap.insertBefore( this[0] );4684       }4685 4686       wrap.map(function() {4687         var elem = this;4688 4689         while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {4690           elem = elem.firstChild;4691         }4692 4693         return elem;4694       }).append(this);4695     }4696 4697     return this;4698   },4699 4700   wrapInner: function( html ) {4701     if ( jQuery.isFunction( html ) ) {4702       return this.each(function(i) {4703         jQuery(this).wrapInner( html.call(this, i) );4704       });4705     }4706 4707     return this.each(function() {4708       var self = jQuery( this ),4709         contents = self.contents();4710 4711       if ( contents.length ) {4712         contents.wrapAll( html );4713 4714       } else {4715         self.append( html );4716       }4717     });4718   },4719 4720   wrap: function( html ) {4721     return this.each(function() {4722       jQuery( this ).wrapAll( html );4723     });4724   },4725 4726   unwrap: function() {4727     return this.parent().each(function() {4728       if ( !jQuery.nodeName( this, "body" ) ) {4729         jQuery( this ).replaceWith( this.childNodes );4730       }4731     }).end();4732   },4733 4734   append: function() {4735     return this.domManip(arguments, true, function( elem ) {4736       if ( this.nodeType === 1 ) {4737         this.appendChild( elem );4738       }4739     });4740   },4741 4742   prepend: function() {4743     return this.domManip(arguments, true, function( elem ) {4744       if ( this.nodeType === 1 ) {4745         this.insertBefore( elem, this.firstChild );4746       }4747     });4748   },4749 4750   before: function() {4751     if ( this[0] && this[0].parentNode ) {4752       return this.domManip(arguments, false, function( elem ) {4753         this.parentNode.insertBefore( elem, this );4754       });4755     } else if ( arguments.length ) {4756       var set = jQuery(arguments[0]);4757       set.push.apply( set, this.toArray() );4758       return this.pushStack( set, "before", arguments );4759     }4760   },4761 4762   after: function() {4763     if ( this[0] && this[0].parentNode ) {4764       return this.domManip(arguments, false, function( elem ) {4765         this.parentNode.insertBefore( elem, this.nextSibling );4766       });4767     } else if ( arguments.length ) {4768       var set = this.pushStack( this, "after", arguments );4769       set.push.apply( set, jQuery(arguments[0]).toArray() );4770       return set;4771     }4772   },4773   4774   // keepData is for internal use only--do not document4775   remove: function( selector, keepData ) {4776     for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {4777       if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {4778         if ( !keepData && elem.nodeType === 1 ) {4779           jQuery.cleanData( elem.getElementsByTagName("*") );4780           jQuery.cleanData( [ elem ] );4781         }4782 4783         if ( elem.parentNode ) {4784            elem.parentNode.removeChild( elem );4785         }4786       }4787     }4788     4789     return this;4790   },4791 4792   empty: function() {4793     for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {4794       // Remove element nodes and prevent memory leaks4795       if ( elem.nodeType === 1 ) {4796         jQuery.cleanData( elem.getElementsByTagName("*") );4797       }4798 4799       // Remove any remaining nodes4800       while ( elem.firstChild ) {4801         elem.removeChild( elem.firstChild );4802       }4803     }4804     4805     return this;4806   },4807 4808   clone: function( events ) {4809     // Do the clone4810     var ret = this.map(function() {4811       if ( !jQuery.support.noCloneEvent && !jQuery.isthis) ) {4812         // IE copies events bound via attachEvent when4813         // using cloneNode. Calling detachEvent on the4814         // clone will also remove the events from the orignal4815         // In order to get around this, we use innerHTML.4816         // Unfortunately, this means some modifications to4817         // attributes in IE that are actually only stored4818         // as properties will not be copied (such as the4819         // the name attribute on an input).4820         var html = this.outerHTML,4821           ownerDocument = this.ownerDocument;4822 4823         if ( !html ) {4824           var div = ownerDocument.createElement("div");4825           div.appendChild( this.cloneNode(true) );4826           html = div.innerHTML;4827         }4828 4829         return jQuery.clean([html.replace(rinlinejQuery, "")4830           // Handle the case in IE 8 where action=/test/> self-closes a tag4831           .replace(raction, '="$1">')4832           .replace(rleadingWhitespace, "")], ownerDocument)[0];4833       } else {4834         return this.cloneNode(true);4835       }4836     });4837 4838     // Copy the events from the original to the clone4839     if ( events === true ) {4840       cloneCopyEvent( this, ret );4841       cloneCopyEvent( this.find("*"), ret.find("*") );4842     }4843 4844     // Return the cloned set4845     return ret;4846   },4847 4848   html: function( value ) {4849     if ( value === undefined ) {4850       return this[0] && this[0].nodeType === 1 ?4851         this[0].innerHTML.replace(rinlinejQuery, "") :4852         null;4853 4854     // See if we can take a shortcut and just use innerHTML4855     } else if ( typeof value === "string" && !rnocache.test( value ) &&4856       (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&4857       !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {4858 4859       value = value.replace(rxhtmlTag, "<$1></$2>");4860 4861       try {4862         for ( var i = 0, l = this.length; i < l; i++ ) {4863           // Remove element nodes and prevent memory leaks4864           if ( this[i].nodeType === 1 ) {4865             jQuery.cleanData( this[i].getElementsByTagName("*") );4866             this[i].innerHTML = value;4867           }4868         }4869 4870       // If using innerHTML throws an exception, use the fallback method4871       } catch(e) {4872         this.empty().append( value );4873       }4874 4875     } else if ( jQuery.isFunction( value ) ) {4876       this.each(function(i){4877         var self = jQuery( this );4878 4879         self.html( value.call(this, i, self.html()) );4880       });4881 4882     } else {4883       this.empty().append( value );4884     }4885 4886     return this;4887   },4888 4889   replaceWith: function( value ) {4890     if ( this[0] && this[0].parentNode ) {4891       // Make sure that the elements are removed from the DOM before they are inserted4892       // this can help fix replacing a parent with child elements4893       if ( jQuery.isFunction( value ) ) {4894         return this.each(function(i) {4895           var self = jQuery(this), old = self.html();4896           self.replaceWith( value.call( this, i, old ) );4897         });4898       }4899 4900       if ( typeof value !== "string" ) {4901         value = jQuery( value ).detach();4902       }4903 4904       return this.each(function() {4905         var next = this.nextSibling,4906           parent = this.parentNode;4907 4908         jQuery( this ).remove();4909 4910         if ( next ) {4911           jQuery(next).before( value );4912         } else {4913           jQuery(parent).append( value );4914         }4915       });4916     } else {4917       return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );4918     }4919   },4920 4921   detach: function( selector ) {4922     return this.remove( selector, true );4923   },4924 4925   domManip: function( args, table, callback ) {4926     var results, first, fragment, parent,4927       value = args[0],4928       scripts = [];4929 4930     // We can't cloneNode fragments that contain checked, in WebKit4931     if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {4932       return this.each(function() {4933         jQuery(this).domManip( args, table, callback, true );4934       });4935     }4936 4937     if ( jQuery.isFunction(value) ) {4938       return this.each(function(i) {4939         var self = jQuery(this);4940         args[0] = value.call(this, i, table ? self.html() : undefined);4941         self.domManip( args, table, callback );4942       });4943     }4944 4945     if ( this[0] ) {4946       parent = value && value.parentNode;4947 4948       // If we're in a fragment, just use that instead of building a new one4949       if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {4950         results = { fragment: parent };4951 4952       } else {4953         results = jQuery.buildFragment( args, this, scripts );4954       }4955       4956       fragment = results.fragment;4957       4958       if ( fragment.childNodes.length === 1 ) {4959         first = fragment = fragment.firstChild;4960       } else {4961         first = fragment.firstChild;4962       }4963 4964       if ( first ) {4965         table = table && jQuery.nodeName( first, "tr" );4966 4967         for ( var i = 0, l = this.length; i < l; i++ ) {4968           callback.call(4969             table ?4970               root(this[i], first) :4971               this[i],4972             i > 0 || results.cacheable || this.length > 1 ?4973               fragment.cloneNode(true) :4974               fragment4975           );4976         }4977       }4978 4979       if ( scripts.length ) {4980         jQuery.each( scripts, evalScript );4981       }4982     }4983 4984     return this;4985   }4986 });4987 4988 function root( elem, cur ) {4989   return jQuery.nodeName(elem, "table") ?4990     (elem.getElementsByTagName("tbody")[0] ||4991     elem.appendChild(elem.ownerDocument.createElement("tbody"))) :4992     elem;4993 }4994 4995 function cloneCopyEvent(orig, ret) {4996   var i = 0;4997 4998   ret.each(function() {4999     if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {5000       return;5001     }5002 5003     var oldData = jQuery.data( orig[i++] ),5004       curData = jQuery.data( this, oldData ),5005       events = oldData && oldData.events;5006 5007     if ( events ) {5008       delete curData.handle;5009       curData.events = {};5010 5011       for ( var type in events ) {5012         for ( var handler in events[ type ] ) {5013           jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );5014         }5015       }5016     }5017   });5018 }5019 5020 jQuery.buildFragment = function( args, nodes, scripts ) {5021   var fragment, cacheable, cacheresults,5022     doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);5023 5024   // Only cache "small" (1/2 KB) strings that are associated with the main document5025   // Cloning options loses the selected state, so don't cache them5026   // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment5027   // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache5028   if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&5029     !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {5030 5031     cacheable = true;5032     cacheresults = jQuery.fragments[ args[0] ];5033     if ( cacheresults ) {5034       if ( cacheresults !== 1 ) {5035         fragment = cacheresults;5036       }5037     }5038   }5039 5040   if ( !fragment ) {5041     fragment = doc.createDocumentFragment();5042     jQuery.clean( args, doc, fragment, scripts );5043   }5044 5045   if ( cacheable ) {5046     jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;5047   }5048 5049   return { fragment: fragment, cacheable: cacheable };5050 };5051 5052 jQuery.fragments = {};5053 5054 jQuery.each({5055   appendTo: "append",5056   prependTo: "prepend",5057   insertBefore: "before",5058   insertAfter: "after",5059   replaceAll: "replaceWith"5060 }, function( name, original ) {5061   jQuery.fn[ name ] = function( selector ) {5062     var ret = [],5063       insert = jQuery( selector ),5064       parent = this.length === 1 && this[0].parentNode;5065     5066     if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {5067       insert[ original ]( this[0] );5068       return this;5069       5070     } else {5071       for ( var i = 0, l = insert.length; i < l; i++ ) {5072         var elems = (i > 0 ? this.clone(true) : this).get();5073         jQuery( insert[i] )[ original ]( elems );5074         ret = ret.concat( elems );5075       }5076     5077       return this.pushStack( ret, name, insert.selector );5078     }5079   };5080 });5081 5082 jQuery.extend({5083   clean: function( elems, context, fragment, scripts ) {5084     context = context || document;5085 5086     // !context.createElement fails in IE with an error but returns typeof 'object'5087     if ( typeof context.createElement === "undefined" ) {5088       context = context.ownerDocument || context[0] && context[0].ownerDocument || document;5089     }5090 5091     var ret = [];5092 5093     for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {5094       if ( typeof elem === "number" ) {5095         elem += "";5096       }5097 5098       if ( !elem ) {5099         continue;5100       }5101 5102       // Convert html string into DOM nodes5103       if ( typeof elem === "string" && !rhtml.test( elem ) ) {5104         elem = context.createTextNode( elem );5105 5106       } else if ( typeof elem === "string" ) {5107         // Fix "XHTML"-style tags in all browsers5108         elem = elem.replace(rxhtmlTag, "<$1></$2>");5109 5110         // Trim whitespace, otherwise indexOf won't work as expected5111         var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),5112           wrap = wrapMap[ tag ] || wrapMap._default,5113           depth = wrap[0],5114           div = context.createElement("div");5115 5116         // Go to html and back, then peel off extra wrappers5117         div.innerHTML = wrap[1] + elem + wrap[2];5118 5119         // Move to the right depth5120         while ( depth-- ) {5121           div = div.lastChild;5122         }5123 5124         // Remove IE's autoinserted <tbody> from table fragments5125         if ( !jQuery.support.tbody ) {5126 5127           // String was a <table>, *may* have spurious <tbody>5128           var hasBody = rtbody.test(elem),5129             tbody = tag === "table" && !hasBody ?5130               div.firstChild && div.firstChild.childNodes :5131 5132               // String was a bare <thead> or <tfoot>5133               wrap[1] === "<table>" && !hasBody ?5134                 div.childNodes :5135                 [];5136 5137           for ( var j = tbody.length - 1; j >= 0 ; --j ) {5138             if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {5139               tbody[ j ].parentNode.removeChild( tbody[ j ] );5140             }5141           }5142 5143         }5144 5145         // IE completely kills leading whitespace when innerHTML is used5146         if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {5147           div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );5148         }5149 5150         elem = div.childNodes;5151       }5152 5153       if ( elem.nodeType ) {5154         ret.push( elem );5155       } else {5156         ret = jQuery.merge( ret, elem );5157       }5158     }5159 5160     if ( fragment ) {5161       for ( i = 0; ret[i]; i++ ) {5162         if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {5163           scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );5164         5165         } else {5166           if ( ret[i].nodeType === 1 ) {5167             ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );5168           }5169           fragment.appendChild( ret[i] );5170         }5171       }5172     }5173 5174     return ret;5175   },5176   5177   cleanData: function( elems ) {5178     var data, id, cache = jQuery.cache,5179       special = jQuery.event.special,5180       deleteExpando = jQuery.support.deleteExpando;5181     5182     for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {5183       if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {5184         continue;5185       }5186 5187       id = elem[ jQuery.expando ];5188       5189       if ( id ) {5190         data = cache[ id ];5191         5192         if ( data && data.events ) {5193           for ( var type in data.events ) {5194             if ( special[ type ] ) {5195               jQuery.event.remove( elem, type );5196 5197             } else {5198               jQuery.removeEvent( elem, type, data.handle );5199             }5200           }5201         }5202         5203         if ( deleteExpando ) {5204           delete elem[ jQuery.expando ];5205 5206         } else if ( elem.removeAttribute ) {5207           elem.removeAttribute( jQuery.expando );5208         }5209         5210         delete cache[ id ];5211       }5212     }5213   }5214 });5215 5216 function evalScript( i, elem ) {5217   if ( elem.src ) {5218     jQuery.ajax({5219       url: elem.src,5220       async: false,5221       dataType: "script"5222     });5223   } else {5224     jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );5225   }5226 5227   if ( elem.parentNode ) {5228     elem.parentNode.removeChild( elem );5229   }5230 }5231 5232 5233 5234 5235 var ralpha = /alpha\([^)]*\)/i,5236   ropacity = /opacity=([^)]*)/,5237   rdashAlpha = /-([a-z])/ig,5238   rupper = /([A-Z])/g,5239   rnumpx = /^-?\d+(?:px)?$/i,5240   rnum = /^-?\d/,5241 5242   cssShow = { position: "absolute", visibility: "hidden", display: "block" },5243   cssWidth = [ "Left", "Right" ],5244   cssHeight = [ "Top", "Bottom" ],5245   curCSS,5246 5247   getComputedStyle,5248   currentStyle,5249 5250   fcamelCase = function( all, letter ) {5251     return letter.toUpperCase();5252   };5253 5254 jQuery.fn.css = function( name, value ) {5255   // Setting 'undefined' is a no-op5256   if ( arguments.length === 2 && value === undefined ) {5257     return this;5258   }5259 5260   return jQuery.access( this, name, value, true, function( elem, name, value ) {5261     return value !== undefined ?5262       jQuery.style( elem, name, value ) :5263       jQuery.css( elem, name );5264   });5265 };5266 5267 jQuery.extend({5268   // Add in style property hooks for overriding the default5269   // behavior of getting and setting a style property5270   cssHooks: {5271     opacity: {5272       get: function( elem, computed ) {5273         if ( computed ) {5274           // We should always get a number back from opacity5275           var ret = curCSS( elem, "opacity", "opacity" );5276           return ret === "" ? "1" : ret;5277 5278         } else {5279           return elem.style.opacity;5280         }5281       }5282     }5283   },5284 5285   // Exclude the following css properties to add px5286   cssNumber: {5287     "zIndex": true,5288     "fontWeight": true,5289     "opacity": true,5290     "zoom": true,5291     "lineHeight": true5292   },5293 5294   // Add in properties whose names you wish to fix before5295   // setting or getting the value5296   cssProps: {5297     // normalize float css property5298     "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"5299   },5300 5301   // Get and set the style property on a DOM Node5302   style: function( elem, name, value, extra ) {5303     // Don't set styles on text and comment nodes5304     if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {5305       return;5306     }5307 5308     // Make sure that we're working with the right name5309     var ret, origName = jQuery.camelCase( name ),5310       style = elem.style, hooks = jQuery.cssHooks[ origName ];5311 5312     name = jQuery.cssProps[ origName ] || origName;5313 5314     // Check if we're setting a value5315     if ( value !== undefined ) {5316       // Make sure that NaN and null values aren't set. See: #71165317       if ( typeof value === "number" && isNaN( value ) || value == null ) {5318         return;5319       }5320 5321       // If a number was passed in, add 'px' to the (except for certain CSS properties)5322       if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) {5323         value += "px";5324       }5325 5326       // If a hook was provided, use that value, otherwise just set the specified value5327       if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {5328         // Wrapped to prevent IE from throwing errors when 'invalid' values are provided5329         // Fixes bug #55095330         try {5331           style[ name ] = value;5332         } catch(e) {}5333       }5334 5335     } else {5336       // If a hook was provided get the non-computed value from there5337       if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {5338         return ret;5339       }5340 5341       // Otherwise just get the value from the style object5342       return style[ name ];5343     }5344   },5345 5346   css: function( elem, name, extra ) {5347     // Make sure that we're working with the right name5348     var ret, origName = jQuery.camelCase( name ),5349       hooks = jQuery.cssHooks[ origName ];5350 5351     name = jQuery.cssProps[ origName ] || origName;5352 5353     // If a hook was provided get the computed value from there5354     if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {5355       return ret;5356 5357     // Otherwise, if a way to get the computed value exists, use that5358     } else if ( curCSS ) {5359       return curCSS( elem, name, origName );5360     }5361   },5362 5363   // A method for quickly swapping in/out CSS properties to get correct calculations5364   swap: function( elem, options, callback ) {5365     var old = {};5366 5367     // Remember the old values, and insert the new ones5368     for ( var name in options ) {5369       old[ name ] = elem.style[ name ];5370       elem.style[ name ] = options[ name ];5371     }5372 5373     callback.call( elem );5374 5375     // Revert the old values5376     for ( name in options ) {5377       elem.style[ name ] = old[ name ];5378     }5379   },5380 5381   camelCase: function( string ) {5382     return string.replace( rdashAlpha, fcamelCase );5383   }5384 });5385 5386 // DEPRECATED, Use jQuery.css() instead5387 jQuery.curCSS = jQuery.css;5388 5389 jQuery.each(["height", "width"], function( i, name ) {5390   jQuery.cssHooks[ name ] = {5391     get: function( elem, computed, extra ) {5392       var val;5393 5394       if ( computed ) {5395         if ( elem.offsetWidth !== 0 ) {5396           val = getWH( elem, name, extra );5397 5398         } else {5399           jQuery.swap( elem, cssShow, function() {5400             val = getWH( elem, name, extra );5401           });5402         }5403 5404         if ( val <= 0 ) {5405           val = curCSS( elem, name, name );5406 5407           if ( val === "0px" && currentStyle ) {5408             val = currentStyle( elem, name, name );5409           }5410 5411           if ( val != null ) {5412             // Should return "auto" instead of 0, use 0 for5413             // temporary backwards-compat5414             return val === "" || val === "auto" ? "0px" : val;5415           }5416         }5417 5418         if ( val < 0 || val == null ) {5419           val = elem.style[ name ];5420 5421           // Should return "auto" instead of 0, use 0 for5422           // temporary backwards-compat5423           return val === "" || val === "auto" ? "0px" : val;5424         }5425 5426         return typeof val === "string" ? val : val + "px";5427       }5428     },5429 5430     set: function( elem, value ) {5431       if ( rnumpx.test( value ) ) {5432         // ignore negative width and height values #15995433         value = parseFloat(value);5434 5435         if ( value >= 0 ) {5436           return value + "px";5437         }5438 5439       } else {5440         return value;5441       }5442     }5443   };5444 });5445 5446 if ( !jQuery.support.opacity ) {5447   jQuery.cssHooks.opacity = {5448     get: function( elem, computed ) {5449       // IE uses filters for opacity5450       return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ?5451         (parseFloat(RegExp.$1) / 100) + "" :5452         computed ? "1" : "";5453     },5454 5455     set: function( elem, value ) {5456       var style = elem.style;5457 5458       // IE has trouble with opacity if it does not have layout5459       // Force it by setting the zoom level5460       style.zoom = 1;5461 5462       // Set the alpha filter to set the opacity5463       var opacity = jQuery.isNaN(value) ?5464         "" :5465         "alpha(opacity=" + value * 100 + ")",5466         filter = style.filter || "";5467 5468       style.filter = ralpha.test(filter) ?5469         filter.replace(ralpha, opacity) :5470         style.filter + ' ' + opacity;5471     }5472   };5473 }5474 5475 if ( document.defaultView && document.defaultView.getComputedStyle ) {5476   getComputedStyle = function( elem, newName, name ) {5477     var ret, defaultView, computedStyle;5478 5479     name = name.replace( rupper, "-$1" ).toLowerCase();5480 5481     if ( !(defaultView = elem.ownerDocument.defaultView) ) {5482       return undefined;5483     }5484 5485     if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {5486       ret = computedStyle.getPropertyValue( name );5487       if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {5488         ret = jQuery.style( elem, name );5489       }5490     }5491 5492     return ret;5493   };5494 }5495 5496 if ( document.documentElement.currentStyle ) {5497   currentStyle = function( elem, name ) {5498     var left, rsLeft,5499       ret = elem.currentStyle && elem.currentStyle[ name ],5500       style = elem.style;5501 5502     // From the awesome hack by Dean Edwards5503     // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-1022915504 5505     // If we're not dealing with a regular pixel number5506     // but a number that has a weird ending, we need to convert it to pixels5507     if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {5508       // Remember the original values5509       left = style.left;5510       rsLeft = elem.runtimeStyle.left;5511 5512       // Put in the new values to get a computed value out5513       elem.runtimeStyle.left = elem.currentStyle.left;5514       style.left = name === "fontSize" ? "1em" : (ret || 0);5515       ret = style.pixelLeft + "px";5516 5517       // Revert the changed values5518       style.left = left;5519       elem.runtimeStyle.left = rsLeft;5520     }5521 5522     return ret === "" ? "auto" : ret;5523   };5524 }5525 5526 curCSS = getComputedStyle || currentStyle;5527 5528 function getWH( elem, name, extra ) {5529   var which = name === "width" ? cssWidth : cssHeight,5530     val = name === "width" ? elem.offsetWidth : elem.offsetHeight;5531 5532   if ( extra === "border" ) {5533     return val;5534   }5535 5536   jQuery.each( which, function() {5537     if ( !extra ) {5538       val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0;5539     }5540 5541     if ( extra === "margin" ) {5542       val += parseFloat(jQuery.css( elem, "margin" + this )) || 0;5543 5544     } else {5545       val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0;5546     }5547   });5548 5549   return val;5550 }5551 5552 if ( jQuery.expr && jQuery.expr.filters ) {5553   jQuery.expr.filters.hidden = function( elem ) {5554     var width = elem.offsetWidth,5555       height = elem.offsetHeight;5556 5557     return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");5558   };5559 5560   jQuery.expr.filters.visible = function( elem ) {5561     return !jQuery.expr.filters.hidden( elem );5562   };5563 }5564 5565 5566 5567 5568 var jsc = jQuery.now(),5569   rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,5570   rselectTextarea = /^(?:select|textarea)/i,5571   rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,5572   rnoContent = /^(?:GET|HEAD)$/,5573   rbracket = /\[\]$/,5574   jsre = /\=\?(&|$)/,5575   rquery = /\?/,5576   rts = /([?&])_=[^&]*/,5577   rurl = /^(\w+:)?\/\/([^\/?#]+)/,5578   r20 = /%20/g,5579   rhash = /#.*$/,5580 5581   // Keep a copy of the old load method5582   _load = jQuery.fn.load;5583 5584 jQuery.fn.extend({5585   load: function( url, params, callback ) {5586     if ( typeof url !== "string" && _load ) {5587       return _load.apply( this, arguments );5588 5589     // Don't do a request if no elements are being requested5590     } else if ( !this.length ) {5591       return this;5592     }5593 5594     var off = url.indexOf(" ");5595     if ( off >= 0 ) {5596       var selector = url.slice(off, url.length);5597       url = url.slice(0, off);5598     }5599 5600     // Default to a GET request5601     var type = "GET";5602 5603     // If the second parameter was provided5604     if ( params ) {5605       // If it's a function5606       if ( jQuery.isFunction( params ) ) {5607         // We assume that it's the callback5608         callback = params;5609         params = null;5610 5611       // Otherwise, build a param string5612       } else if ( typeof params === "object" ) {5613         params = jQuery.param( params, jQuery.ajaxSettings.traditional );5614         type = "POST";5615       }5616     }5617 5618     var self = this;5619 5620     // Request the remote document5621     jQuery.ajax({5622       url: url,5623       type: type,5624       dataType: "html",5625       data: params,5626       complete: function( res, status ) {5627         // If successful, inject the HTML into all the matched elements5628         if ( status === "success" || status === "notmodified" ) {5629           // See if a selector was specified5630           self.html( selector ?5631             // Create a dummy div to hold the results5632             jQuery("<div>")5633               // inject the contents of the document in, removing the scripts5634               // to avoid any 'Permission Denied' errors in IE5635               .append(res.responseText.replace(rscript, ""))5636 5637               // Locate the specified elements5638               .find(selector) :5639 5640             // If not, just inject the full result5641             res.responseText );5642         }5643 5644         if ( callback ) {5645           self.each( callback, [res.responseText, status, res] );5646         }5647       }5648     });5649 5650     return this;5651   },5652 5653   serialize: function() {5654     return jQuery.param(this.serializeArray());5655   },5656 5657   serializeArray: function() {5658     return this.map(function() {5659       return this.elements ? jQuery.makeArray(this.elements) : this;5660     })5661     .filter(function() {5662       return this.name && !this.disabled &&5663         (this.checked || rselectTextarea.test(this.nodeName) ||5664           rinput.test(this.type));5665     })5666     .map(function( i, elem ) {5667       var val = jQuery(this).val();5668 5669       return val == null ?5670         null :5671         jQuery.isArray(val) ?5672           jQuery.map( val, function( val, i ) {5673             return { name: elem.name, value: val };5674           }) :5675           { name: elem.name, value: val };5676     }).get();5677   }5678 });5679 5680 // Attach a bunch of functions for handling common AJAX events5681 jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {5682   jQuery.fn[o] = function( f ) {5683     return this.bind(o, f);5684   };5685 });5686 5687 jQuery.extend({5688   get: function( url, data, callback, type ) {5689     // shift arguments if data argument was omited5690     if ( jQuery.isFunction( data ) ) {5691       type = type || callback;5692       callback = data;5693       data = null;5694     }5695 5696     return jQuery.ajax({5697       type: "GET",5698       url: url,5699       data: data,5700       success: callback,5701       dataType: type5702     });5703   },5704 5705   getScript: function( url, callback ) {5706     return jQuery.get(url, null, callback, "script");5707   },5708 5709   getJSON: function( url, data, callback ) {5710     return jQuery.get(url, data, callback, "json");5711   },5712 5713   post: function( url, data, callback, type ) {5714     // shift arguments if data argument was omited5715     if ( jQuery.isFunction( data ) ) {5716       type = type || callback;5717       callback = data;5718       data = {};5719     }5720 5721     return jQuery.ajax({5722       type: "POST",5723       url: url,5724       data: data,5725       success: callback,5726       dataType: type5727     });5728   },5729 5730   ajaxSetup: function( settings ) {5731     jQuery.extend( jQuery.ajaxSettings, settings );5732   },5733 5734   ajaxSettings: {5735     url: location.href,5736     global: true,5737     type: "GET",5738     contentType: "application/x-www-form-urlencoded",5739     processData: true,5740     async: true,5741     /*5742     timeout: 0,5743     data: null,5744     username: null,5745     password: null,5746     traditional: false,5747     */5748     // This function can be overriden by calling jQuery.ajaxSetup5749     xhr: function() {5750       return new window.5751     },5752     accepts: {5753       ,5754       html: "text/html",5755       script: "text/javascript, application/javascript",5756       json: "application/json, text/javascript",5757       text: "text/plain",5758       _default: "*/*"5759     }5760   },5761 5762   ajax: function( origSettings ) {5763     var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings),5764       jsonp, status, data, type = s.type.toUpperCase(), noContent = rnoContent.test(type);5765 5766     s.url = s.url.replace( rhash, "" );5767 5768     // Use original (not extended) context object if it was provided5769     s.context = origSettings && origSettings.context != null ? origSettings.context : s;5770 5771     // convert data if not already a string5772     if ( s.data && s.processData && typeof s.data !== "string" ) {5773       s.data = jQuery.param( s.data, s.traditional );5774     }5775 5776     // Handle JSONP Parameter Callbacks5777     if ( s.dataType === "jsonp" ) {5778       if ( type === "GET" ) {5779         if ( !jsre.test( s.url ) ) {5780           s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";5781         }5782       } else if ( !s.data || !jsre.test(s.data) ) {5783         s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";5784       }5785       s.dataType = "json";5786     }5787 5788     // Build temporary JSONP function5789     if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {5790       jsonp = s.jsonpCallback || ("jsonp" + jsc++);5791 5792       // Replace the =? sequence both in the query string and the data5793       if ( s.data ) {5794         s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");5795       }5796 5797       s.url = s.url.replace(jsre, "=" + jsonp + "$1");5798 5799       // We need to make sure5800       // that a JSONP style response is executed properly5801       s.dataType = "script";5802 5803       // Handle JSONP-style loading5804       var customJsonp = window[ jsonp ];5805 5806       window[ jsonp ] = function( tmp ) {5807         if ( jQuery.isFunction( customJsonp ) ) {5808           customJsonp( tmp );5809 5810         } else {5811           // Garbage collect5812           window[ jsonp ] = undefined;5813 5814           try {5815             delete window[ jsonp ];5816           } catch( jsonpError ) {}5817         }5818 5819         data = tmp;5820         jQuery.handleSuccess( s, xhr, status, data );5821         jQuery.handleComplete( s, xhr, status, data );5822         5823         if ( head ) {5824           head.removeChild( script );5825         }5826       };5827     }5828 5829     if ( s.dataType === "script" && s.cache === null ) {5830       s.cache = false;5831     }5832 5833     if ( s.cache === false && noContent ) {5834       var ts = jQuery.now();5835 5836       // try replacing _= if it is there5837       var ret = s.url.replace(rts, "$1_=" + ts);5838 5839       // if nothing was replaced, add timestamp to the end5840       s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");5841     }5842 5843     // If data is available, append data to url for GET/HEAD requests5844     if ( s.data && noContent ) {5845       s.url += (rquery.test(s.url) ? "&" : "?") + s.data;5846     }5847 5848     // Watch for a new set of requests5849     if ( s.global && jQuery.active++ === 0 ) {5850       jQuery.event.trigger( "ajaxStart" );5851     }5852 5853     // Matches an absolute URL, and saves the domain5854     var parts = rurl.exec( s.url ),5855       remote = parts && (parts[1] && parts[1].toLowerCase() !== location.protocol || parts[2].toLowerCase() !== location.host);5856 5857     // If we're requesting a remote document5858     // and trying to load JSON or Script with a GET5859     if ( s.dataType === "script" && type === "GET" && remote ) {5860       var head = document.getElementsByTagName("head")[0] || document.documentElement;5861       var script = document.createElement("script");5862       if ( s.scriptCharset ) {5863         script.charset = s.scriptCharset;5864       }5865       script.src = s.url;5866 5867       // Handle Script loading5868       if ( !jsonp ) {5869         var done = false;5870 5871         // Attach handlers for all browsers5872         script.onload = script.onreadystatechange = function() {5873           if ( !done && (!this.readyState ||5874               this.readyState === "loaded" || this.readyState === "complete") ) {5875             done = true;5876             jQuery.handleSuccess( s, xhr, status, data );5877             jQuery.handleComplete( s, xhr, status, data );5878 5879             // Handle memory leak in IE5880             script.onload = script.onreadystatechange = null;5881             if ( head && script.parentNode ) {5882               head.removeChild( script );5883             }5884           }5885         };5886       }5887 5888       // Use insertBefore instead of appendChild to circumvent an IE6 bug.5889       // This arises when a base node is used (#2709 and #4378).5890       head.insertBefore( script, head.firstChild );5891 5892       // We handle everything using the script element injection5893       return undefined;5894     }5895 5896     var requestDone = false;5897 5898     // Create the request object5899     var xhr = s.xhr();5900 5901     if ( !xhr ) {5902       return;5903     }5904 5905     // Open the socket5906     // Passing null username, generates a login popup on Opera (#2865)5907     if ( s.username ) {5908       xhr.open(type, s.url, s.async, s.username, s.password);5909     } else {5910       xhr.open(type, s.url, s.async);5911     }5912 5913     // Need an extra try/catch for cross domain requests in Firefox 35914     try {5915       // Set content-type if data specified and content-body is valid for this type5916       if ( (s.data != null && !noContent) || (origSettings && origSettings.contentType) ) {5917         xhr.setRequestHeader("Content-Type", s.contentType);5918       }5919 5920       // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.5921       if ( s.ifModified ) {5922         if ( jQuery.lastModified[s.url] ) {5923           xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);5924         }5925 5926         if ( jQuery.etag[s.url] ) {5927           xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);5928         }5929       }5930 5931       // Set header so the called script knows that it's an 5932       // Only send the header if it's not a remote XHR5933       if ( !remote ) {5934         xhr.setRequestHeader("X-Requested-With", ");5935       }5936 5937       // Set the Accepts header for the server, depending on the dataType5938       xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?5939         s.accepts[ s.dataType ] + ", */*; q=0.01" :5940         s.accepts._default );5941     } catch( headerError ) {}5942 5943     // Allow custom headers/mimetypes and early abort5944     if ( s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false ) {5945       // Handle the global AJAX counter5946       if ( s.global && jQuery.active-- === 1 ) {5947         jQuery.event.trigger( "ajaxStop" );5948       }5949 5950       // close opended socket5951       xhr.abort();5952       return false;5953     }5954 5955     if ( s.global ) {5956       jQuery.triggerGlobal( s, "ajaxSend", [xhr, s] );5957     }5958 5959     // Wait for a response to come back5960     var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {5961       // The request was aborted5962       if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {5963         // Opera doesn't call onreadystatechange before this point5964         // so we simulate the call5965         if ( !requestDone ) {5966           jQuery.handleComplete( s, xhr, status, data );5967         }5968 5969         requestDone = true;5970         if ( xhr ) {5971           xhr.onreadystatechange = jQuery.noop;5972         }5973 5974       // The transfer is complete and the data is available, or the request timed out5975       } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {5976         requestDone = true;5977         xhr.onreadystatechange = jQuery.noop;5978 5979         status = isTimeout === "timeout" ?5980           "timeout" :5981           !jQuery.httpSuccess( xhr ) ?5982             "error" :5983             s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?5984               "notmodified" :5985               "success";5986 5987         var errMsg;5988 5989         if ( status === "success" ) {5990           // Watch for, and catch, 5991           try {5992             // process the data (runs the 5993             data = jQuery.httpData( xhr, s.dataType, s );5994           } catch( parserError ) {5995             status = "parsererror";5996             errMsg = parserError;5997           }5998         }5999 6000         // Make sure that the request was successful or notmodified6001         if ( status === "success" || status === "notmodified" ) {6002           // JSONP handles its own success callback6003           if ( !jsonp ) {6004             jQuery.handleSuccess( s, xhr, status, data );6005           }6006         } else {6007           jQuery.handleError( s, xhr, status, errMsg );6008         }6009 6010         // Fire the complete handlers6011         if ( !jsonp ) {6012           jQuery.handleComplete( s, xhr, status, data );6013         }6014 6015         if ( isTimeout === "timeout" ) {6016           xhr.abort();6017         }6018 6019         // Stop memory leaks6020         if ( s.async ) {6021           xhr = null;6022         }6023       }6024     };6025 6026     // Override the abort handler, if we can (IE 6 doesn't allow it, but that's OK)6027     // Opera doesn't fire onreadystatechange at all on abort6028     try {6029       var oldAbort = xhr.abort;6030       xhr.abort = function() {6031         if ( xhr ) {6032           // oldAbort has no call property in IE7 so6033           // just do it this way, which works in all6034           // browsers6035           Function.prototype.call.call( oldAbort, xhr );6036         }6037 6038         onreadystatechange( "abort" );6039       };6040     } catch( abortError ) {}6041 6042     // Timeout checker6043     if ( s.async && s.timeout > 0 ) {6044       setTimeout(function() {6045         // Check to see if the request is still happening6046         if ( xhr && !requestDone ) {6047           onreadystatechange( "timeout" );6048         }6049       }, s.timeout);6050     }6051 6052     // Send the data6053     try {6054       xhr.send( noContent || s.data == null ? null : s.data );6055 6056     } catch( sendError ) {6057       jQuery.handleError( s, xhr, null, sendError );6058 6059       // Fire the complete handlers6060       jQuery.handleComplete( s, xhr, status, data );6061     }6062 6063     // firefox 1.5 doesn't fire statechange for sync requests6064     if ( !s.async ) {6065       onreadystatechange();6066     }6067 6068     // return 6069     return xhr;6070   },6071 6072   // Serialize an array of form elements or a set of6073   // key/values into a query string6074   param: function( a, traditional ) {6075     var s = [],6076       add = function( key, value ) {6077         // If value is a function, invoke it and return its value6078         value = jQuery.isFunction(value) ? value() : value;6079         s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);6080       };6081     6082     // Set traditional to true for jQuery <= 1.3.2 behavior.6083     if ( traditional === undefined ) {6084       traditional = jQuery.ajaxSettings.traditional;6085     }6086     6087     // If an array was passed in, assume that it is an array of form elements.6088     if ( jQuery.isArray(a) || a.jquery ) {6089       // Serialize the form elements6090       jQuery.each( a, function() {6091         add( this.name, this.value );6092       });6093       6094     } else {6095       // If traditional, encode the "old" way (the way 1.3.2 or older6096       // did it), otherwise encode params recursively.6097       for ( var prefix in a ) {6098         buildParams( prefix, a[prefix], traditional, add );6099       }6100     }6101 6102     // Return the resulting serialization6103     return s.join("&").replace(r20, "+");6104   }6105 });6106 6107 function buildParams( prefix, obj, traditional, add ) {6108   if ( jQuery.isArray(obj) && obj.length ) {6109     // Serialize array item.6110     jQuery.each( obj, function( i, v ) {6111       if ( traditional || rbracket.test( prefix ) ) {6112         // Treat each array item as a scalar.6113         add( prefix, v );6114 6115       } else {6116         // If array item is non-scalar (array or object), encode its6117         // numeric index to resolve deserialization ambiguity issues.6118         // Note that rack (as of 1.0.0) can't currently deserialize6119         // nested arrays properly, and attempting to do so may cause6120         // a server error. Possible fixes are to modify rack's6121         // deserialization algorithm or to provide an option or flag6122         // to force array serialization to be shallow.6123         buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );6124       }6125     });6126       6127   } else if ( !traditional && obj != null && typeof obj === "object" ) {6128     if ( jQuery.isEmptyObject( obj ) ) {6129       add( prefix, "" );6130 6131     // Serialize object item.6132     } else {6133       jQuery.each( obj, function( k, v ) {6134         buildParams( prefix + "[" + k + "]", v, traditional, add );6135       });6136     }6137           6138   } else {6139     // Serialize scalar item.6140     add( prefix, obj );6141   }6142 }6143 6144 // This is still on the jQuery object... for now6145 // Want to move this to jQuery.ajax some day6146 jQuery.extend({6147 6148   // Counter for holding the number of active queries6149   active: 0,6150 6151   // Last-Modified header cache for next request6152   lastModified: {},6153   etag: {},6154 6155   handleError: function( s, xhr, status, e ) {6156     // If a local callback was specified, fire it6157     if ( s.error ) {6158       s.error.call( s.context, xhr, status, e );6159     }6160 6161     // Fire the global callback6162     if ( s.global ) {6163       jQuery.triggerGlobal( s, "ajaxError", [xhr, s, e] );6164     }6165   },6166 6167   handleSuccess: function( s, xhr, status, data ) {6168     // If a local callback was specified, fire it and pass it the data6169     if ( s.success ) {6170       s.success.call( s.context, data, status, xhr );6171     }6172 6173     // Fire the global callback6174     if ( s.global ) {6175       jQuery.triggerGlobal( s, "ajaxSuccess", [xhr, s] );6176     }6177   },6178 6179   handleComplete: function( s, xhr, status ) {6180     // Process result6181     if ( s.complete ) {6182       s.complete.call( s.context, xhr, status );6183     }6184 6185     // The request was completed6186     if ( s.global ) {6187       jQuery.triggerGlobal( s, "ajaxComplete", [xhr, s] );6188     }6189 6190     // Handle the global AJAX counter6191     if ( s.global && jQuery.active-- === 1 ) {6192       jQuery.event.trigger( "ajaxStop" );6193     }6194   },6195     6196   triggerGlobal: function( s, type, args ) {6197     (s.context && s.context.url == null ? jQuery(s.context) : jQuery.event).trigger(type, args);6198   },6199 6200   // Determines if an 6201   httpSuccess: function( xhr ) {6202     try {6203       // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #14506204       return !xhr.status && location.protocol === "file:" ||6205         xhr.status >= 200 && xhr.status < 300 ||6206         xhr.status === 304 || xhr.status === 1223;6207     } catch(e) {}6208 6209     return false;6210   },6211 6212   // Determines if an 6213   httpNotModified: function( xhr, url ) {6214     var lastModified = xhr.getResponseHeader("Last-Modified"),6215       etag = xhr.getResponseHeader("Etag");6216 6217     if ( lastModified ) {6218       jQuery.lastModified[url] = lastModified;6219     }6220 6221     if ( etag ) {6222       jQuery.etag[url] = etag;6223     }6224 6225     return xhr.status === 304;6226   },6227 6228   httpData: function( xhr, type, s ) {6229     var ct = xhr.getResponseHeader("content-type") || "",6230       ,6231       data =  xhr.response6232 6233     if (  ) {6234       jQuery.error( "parsererror" );6235     }6236 6237     // Allow a pre-filtering function to sanitize the response6238     // s is checked to keep backwards compatibility6239     if ( s && s.dataFilter ) {6240       data = s.dataFilter( data, type );6241     }6242 6243     // The filter can actually parse the response6244     if ( typeof data === "string" ) {6245       // Get the JavaScript object, if JSON is used.6246       if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {6247         data = jQuery.parseJSON( data );6248 6249       // If the type is "script", eval it in global context6250       } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {6251         jQuery.globalEval( data );6252       }6253     }6254 6255     return data;6256   }6257 6258 });6259 6260 /*6261  * Create the request object; Microsoft failed to properly6262  * implement the 6263  * so we use the ActiveXObject when it is available6264  * Additionally 6265  * we need a fallback.6266 */6267 if ( window.ActiveXObject ) {6268   jQuery.ajaxSettings.xhr = function() {6269     if ( window.location.protocol !== "file:" ) {6270       try {6271         return new window.6272       } catch(xhrError) {}6273     }6274 6275     try {6276       return new window.ActiveXObject("Microsoft.);6277     } catch(activeError) {}6278   };6279 }6280 6281 // Does this browser support XHR requests?6282 jQuery.support.ajax = !!jQuery.ajaxSettings.xhr();6283 6284 6285 6286 6287 var elemdisplay = {},6288   rfxtypes = /^(?:toggle|show|hide)$/,6289   rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/,6290   timerId,6291   fxAttrs = [6292     // height animations6293     [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],6294     // width animations6295     [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],6296     // opacity animations6297     [ "opacity" ]6298   ];6299 6300 jQuery.fn.extend({6301   show: function( speed, easing, callback ) {6302     var elem, display;6303 6304     if ( speed || speed === 0 ) {6305       return this.animate( genFx("show", 3), speed, easing, callback);6306 6307     } else {6308       for ( var i = 0, j = this.length; i < j; i++ ) {6309         elem = this[i];6310         display = elem.style.display;6311 6312         // Reset the inline display of this element to learn if it is6313         // being hidden by cascaded rules or not6314         if ( !jQuery.data(elem, "olddisplay") && display === "none" ) {6315           display = elem.style.display = "";6316         }6317 6318         // Set elements which have been overridden with display: none6319         // in a stylesheet to whatever the default browser style is6320         // for such an element6321         if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {6322           jQuery.data(elem, "olddisplay", defaultDisplay(elem.nodeName));6323         }6324       }6325 6326       // Set the display of most of the elements in a second loop6327       // to avoid the constant reflow6328       for ( i = 0; i < j; i++ ) {6329         elem = this[i];6330         display = elem.style.display;6331 6332         if ( display === "" || display === "none" ) {6333           elem.style.display = jQuery.data(elem, "olddisplay") || "";6334         }6335       }6336 6337       return this;6338     }6339   },6340 6341   hide: function( speed, easing, callback ) {6342     if ( speed || speed === 0 ) {6343       return this.animate( genFx("hide", 3), speed, easing, callback);6344 6345     } else {6346       for ( var i = 0, j = this.length; i < j; i++ ) {6347         var display = jQuery.css( this[i], "display" );6348 6349         if ( display !== "none" ) {6350           jQuery.data( this[i], "olddisplay", display );6351         }6352       }6353 6354       // Set the display of the elements in a second loop6355       // to avoid the constant reflow6356       for ( i = 0; i < j; i++ ) {6357         this[i].style.display = "none";6358       }6359 6360       return this;6361     }6362   },6363 6364   // Save the old toggle function6365   _toggle: jQuery.fn.toggle,6366 6367   toggle: function( fn, fn2, callback ) {6368     var bool = typeof fn === "boolean";6369 6370     if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {6371       this._toggle.apply( this, arguments );6372 6373     } else if ( fn == null || bool ) {6374       this.each(function() {6375         var state = bool ? fn : jQuery(this).is(":hidden");6376         jQuery(this)[ state ? "show" : "hide" ]();6377       });6378 6379     } else {6380       this.animate(genFx("toggle", 3), fn, fn2, callback);6381     }6382 6383     return this;6384   },6385 6386   fadeTo: function( speed, to, easing, callback ) {6387     return this.filter(":hidden").css("opacity", 0).show().end()6388           .animate({opacity: to}, speed, easing, callback);6389   },6390 6391   animate: function( prop, speed, easing, callback ) {6392     var optall = jQuery.speed(speed, easing, callback);6393 6394     if ( jQuery.isEmptyObject( prop ) ) {6395       return this.each( optall.complete );6396     }6397 6398     return this[ optall.queue === false ? "each" : "queue" ](function() {6399       // XXX 'this' does not always have a nodeName when running the6400       // test suite6401 6402       var opt = jQuery.extend({}, optall), p,6403         isElement = this.nodeType === 1,6404         hidden = isElement && jQuery(this).is(":hidden"),6405         self = this;6406 6407       for ( p in prop ) {6408         var name = jQuery.camelCase( p );6409 6410         if ( p !== name ) {6411           prop[ name ] = prop[ p ];6412           delete prop[ p ];6413           p = name;6414         }6415 6416         if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {6417           return opt.complete.call(this);6418         }6419 6420         if ( isElement && ( p === "height" || p === "width" ) ) {6421           // Make sure that nothing sneaks out6422           // Record all 3 overflow attributes because IE does not6423           // change the overflow attribute when overflowX and6424           // overflowY are set to the same value6425           opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];6426 6427           // Set display property to inline-block for height/width6428           // animations on inline elements that are having width/height6429           // animated6430           if ( jQuery.css( this, "display" ) === "inline" &&6431               jQuery.css( this, "float" ) === "none" ) {6432             if ( !jQuery.support.inlineBlockNeedsLayout ) {6433               this.style.display = "inline-block";6434 6435             } else {6436               var display = defaultDisplay(this.nodeName);6437 6438               // inline-level elements accept inline-block;6439               // block-level elements need to be inline with layout6440               if ( display === "inline" ) {6441                 this.style.display = "inline-block";6442 6443               } else {6444                 this.style.display = "inline";6445                 this.style.zoom = 1;6446               }6447             }6448           }6449         }6450 6451         if ( jQuery.isArray( prop[p] ) ) {6452           // Create (if needed) and add to specialEasing6453           (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];6454           prop[p] = prop[p][0];6455         }6456       }6457 6458       if ( opt.overflow != null ) {6459         this.style.overflow = "hidden";6460       }6461 6462       opt.curAnim = jQuery.extend({}, prop);6463 6464       jQuery.each( prop, function( name, val ) {6465         var e = new jQuery.fx( self, opt, name );6466 6467         if ( rfxtypes.test(val) ) {6468           e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );6469 6470         } else {6471           var parts = rfxnum.exec(val),6472             start = e.cur() || 0;6473 6474           if ( parts ) {6475             var end = parseFloat( parts[2] ),6476               unit = parts[3] || "px";6477 6478             // We need to compute starting value6479             if ( unit !== "px" ) {6480               jQuery.style( self, name, (end || 1) + unit);6481               start = ((end || 1) / e.cur()) * start;6482               jQuery.style( self, name, start + unit);6483             }6484 6485             // If a +=/-= token was provided, we're doing a relative animation6486             if ( parts[1] ) {6487               end = ((parts[1] === "-=" ? -1 : 1) * end) + start;6488             }6489 6490             e.custom( start, end, unit );6491 6492           } else {6493             e.custom( start, val, "" );6494           }6495         }6496       });6497 6498       // For JS strict compliance6499       return true;6500     });6501   },6502 6503   stop: function( clearQueue, gotoEnd ) {6504     var timers = jQuery.timers;6505 6506     if ( clearQueue ) {6507       this.queue([]);6508     }6509 6510     this.each(function() {6511       // go in reverse order so anything added to the queue during the loop is ignored6512       for ( var i = timers.length - 1; i >= 0; i-- ) {6513         if ( timers[i].elem === this ) {6514           if (gotoEnd) {6515             // force the next step to be the last6516             timers[i](true);6517           }6518 6519           timers.splice(i, 1);6520         }6521       }6522     });6523 6524     // start the next in the queue if the last step wasn't forced6525     if ( !gotoEnd ) {6526       this.dequeue();6527     }6528 6529     return this;6530   }6531 6532 });6533 6534 function genFx( type, num ) {6535   var obj = {};6536 6537   jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {6538     obj[ this ] = type;6539   });6540 6541   return obj;6542 }6543 6544 // Generate shortcuts for custom animations6545 jQuery.each({6546   slideDown: genFx("show", 1),6547   slideUp: genFx("hide", 1),6548   slideToggle: genFx("toggle", 1),6549   fadeIn: { opacity: "show" },6550   fadeOut: { opacity: "hide" },6551   fadeToggle: { opacity: "toggle" }6552 }, function( name, props ) {6553   jQuery.fn[ name ] = function( speed, easing, callback ) {6554     return this.animate( props, speed, easing, callback );6555   };6556 });6557 6558 jQuery.extend({6559   speed: function( speed, easing, fn ) {6560     var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {6561       complete: fn || !fn && easing ||6562         jQuery.isFunction( speed ) && speed,6563       duration: speed,6564       easing: fn && easing || easing && !jQuery.isFunction(easing) && easing6565     };6566 6567     opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :6568       opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;6569 6570     // Queueing6571     opt.old = opt.complete;6572     opt.complete = function() {6573       if ( opt.queue !== false ) {6574         jQuery(this).dequeue();6575       }6576       if ( jQuery.isFunction( opt.old ) ) {6577         opt.old.call( this );6578       }6579     };6580 6581     return opt;6582   },6583 6584   easing: {6585     linear: function( p, n, firstNum, diff ) {6586       return firstNum + diff * p;6587     },6588     swing: function( p, n, firstNum, diff ) {6589       return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;6590     }6591   },6592 6593   timers: [],6594 6595   fx: function( elem, options, prop ) {6596     this.options = options;6597     this.elem = elem;6598     this.prop = prop;6599 6600     if ( !options.orig ) {6601       options.orig = {};6602     }6603   }6604 6605 });6606 6607 jQuery.fx.prototype = {6608   // Simple function for setting a style value6609   update: function() {6610     if ( this.options.step ) {6611       this.options.step.call( this.elem, this.now, this );6612     }6613 6614     (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );6615   },6616 6617   // Get the current size6618   cur: function() {6619     if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {6620       return this.elem[ this.prop ];6621     }6622 6623     var r = parseFloat( jQuery.css( this.elem, this.prop ) );6624     return r && r > -10000 ? r : 0;6625   },6626 6627   // Start an animation from one number to another6628   custom: function( from, to, unit ) {6629     var self = this,6630       fx = jQuery.fx;6631 6632     this.startTime = jQuery.now();6633     this.start = from;6634     this.end = to;6635     this.unit = unit || this.unit || "px";6636     this.now = this.start;6637     this.pos = this.state = 0;6638 6639     function t( gotoEnd ) {6640       return self.step(gotoEnd);6641     }6642 6643     t.elem = this.elem;6644 6645     if ( t() && jQuery.timers.push(t) && !timerId ) {6646       timerId = setInterval(fx.tick, fx.interval);6647     }6648   },6649 6650   // Simple 'show' function6651   show: function() {6652     // Remember where we started, so that we can go back to it later6653     this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );6654     this.options.show = true;6655 6656     // Begin the animation6657     // Make sure that we start at a small width/height to avoid any6658     // flash of content6659     this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());6660 6661     // Start by showing the element6662     jQuery( this.elem ).show();6663   },6664 6665   // Simple 'hide' function6666   hide: function() {6667     // Remember where we started, so that we can go back to it later6668     this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );6669     this.options.hide = true;6670 6671     // Begin the animation6672     this.custom(this.cur(), 0);6673   },6674 6675   // Each step of an animation6676   step: function( gotoEnd ) {6677     var t = jQuery.now(), done = true;6678 6679     if ( gotoEnd || t >= this.options.duration + this.startTime ) {6680       this.now = this.end;6681       this.pos = this.state = 1;6682       this.update();6683 6684       this.options.curAnim[ this.prop ] = true;6685 6686       for ( var i in this.options.curAnim ) {6687         if ( this.options.curAnim[i] !== true ) {6688           done = false;6689         }6690       }6691 6692       if ( done ) {6693         // Reset the overflow6694         if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {6695           var elem = this.elem,6696             options = this.options;6697 6698           jQuery.each( [ "", "X", "Y" ], function (index, value) {6699             elem.style[ "overflow" + value ] = options.overflow[index];6700           } );6701         }6702 6703         // Hide the element if the "hide" operation was done6704         if ( this.options.hide ) {6705           jQuery(this.elem).hide();6706         }6707 6708         // Reset the properties, if the item has been hidden or shown6709         if ( this.options.hide || this.options.show ) {6710           for ( var p in this.options.curAnim ) {6711             jQuery.style( this.elem, p, this.options.orig[p] );6712           }6713         }6714 6715         // Execute the complete function6716         this.options.complete.call( this.elem );6717       }6718 6719       return false;6720 6721     } else {6722       var n = t - this.startTime;6723       this.state = n / this.options.duration;6724 6725       // Perform the easing function, defaults to swing6726       var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];6727       var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");6728       this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);6729       this.now = this.start + ((this.end - this.start) * this.pos);6730 6731       // Perform the next step of the animation6732       this.update();6733     }6734 6735     return true;6736   }6737 };6738 6739 jQuery.extend( jQuery.fx, {6740   tick: function() {6741     var timers = jQuery.timers;6742 6743     for ( var i = 0; i < timers.length; i++ ) {6744       if ( !timers[i]() ) {6745         timers.splice(i--, 1);6746       }6747     }6748 6749     if ( !timers.length ) {6750       jQuery.fx.stop();6751     }6752   },6753 6754   interval: 13,6755 6756   stop: function() {6757     clearInterval( timerId );6758     timerId = null;6759   },6760 6761   speeds: {6762     slow: 600,6763     fast: 200,6764     // Default speed6765     _default: 4006766   },6767 6768   step: {6769     opacity: function( fx ) {6770       jQuery.style( fx.elem, "opacity", fx.now );6771     },6772 6773     _default: function( fx ) {6774       if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {6775         fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;6776       } else {6777         fx.elem[ fx.prop ] = fx.now;6778       }6779     }6780   }6781 });6782 6783 if ( jQuery.expr && jQuery.expr.filters ) {6784   jQuery.expr.filters.animated = function( elem ) {6785     return jQuery.grep(jQuery.timers, function( fn ) {6786       return elem === fn.elem;6787     }).length;6788   };6789 }6790 6791 function defaultDisplay( nodeName ) {6792   if ( !elemdisplay[ nodeName ] ) {6793     var elem = jQuery("<" + nodeName + ">").appendTo("body"),6794       display = elem.css("display");6795 6796     elem.remove();6797 6798     if ( display === "none" || display === "" ) {6799       display = "block";6800     }6801 6802     elemdisplay[ nodeName ] = display;6803   }6804 6805   return elemdisplay[ nodeName ];6806 }6807 6808 6809 6810 6811 var rtable = /^t(?:able|d|h)$/i,6812   rroot = /^(?:body|html)$/i;6813 6814 if ( "getBoundingClientRect" in document.documentElement ) {6815   jQuery.fn.offset = function( options ) {6816     var elem = this[0], box;6817 6818     if ( options ) { 6819       return this.each(function( i ) {6820         jQuery.offset.setOffset( this, options, i );6821       });6822     }6823 6824     if ( !elem || !elem.ownerDocument ) {6825       return null;6826     }6827 6828     if ( elem === elem.ownerDocument.body ) {6829       return jQuery.offset.bodyOffset( elem );6830     }6831 6832     try {6833       box = elem.getBoundingClientRect();6834     } catch(e) {}6835 6836     var doc = elem.ownerDocument,6837       docElem = doc.documentElement;6838 6839     // Make sure we're not dealing with a disconnected DOM node6840     if ( !box || !jQuery.contains( docElem, elem ) ) {6841       return box || { top: 0, left: 0 };6842     }6843 6844     var body = doc.body,6845       win = getWindow(doc),6846       clientTop = docElem.clientTop || body.clientTop || 0,6847       clientLeft = docElem.clientLeft || body.clientLeft || 0,6848       scrollTop = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ),6849       scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft),6850       top = box.top + scrollTop - clientTop,6851       left = box.left + scrollLeft - clientLeft;6852 6853     return { top: top, left: left };6854   };6855 6856 } else {6857   jQuery.fn.offset = function( options ) {6858     var elem = this[0];6859 6860     if ( options ) { 6861       return this.each(function( i ) {6862         jQuery.offset.setOffset( this, options, i );6863       });6864     }6865 6866     if ( !elem || !elem.ownerDocument ) {6867       return null;6868     }6869 6870     if ( elem === elem.ownerDocument.body ) {6871       return jQuery.offset.bodyOffset( elem );6872     }6873 6874     jQuery.offset.initialize();6875 6876     var computedStyle,6877       offsetParent = elem.offsetParent,6878       prevOffsetParent = elem,6879       doc = elem.ownerDocument,6880       docElem = doc.documentElement,6881       body = doc.body,6882       defaultView = doc.defaultView,6883       prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,6884       top = elem.offsetTop,6885       left = elem.offsetLeft;6886 6887     while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {6888       if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {6889         break;6890       }6891 6892       computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;6893       top -= elem.scrollTop;6894       left -= elem.scrollLeft;6895 6896       if ( elem === offsetParent ) {6897         top += elem.offsetTop;6898         left += elem.offsetLeft;6899 6900         if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {6901           top += parseFloat( computedStyle.borderTopWidth ) || 0;6902           left += parseFloat( computedStyle.borderLeftWidth ) || 0;6903         }6904 6905         prevOffsetParent = offsetParent;6906         offsetParent = elem.offsetParent;6907       }6908 6909       if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {6910         top += parseFloat( computedStyle.borderTopWidth ) || 0;6911         left += parseFloat( computedStyle.borderLeftWidth ) || 0;6912       }6913 6914       prevComputedStyle = computedStyle;6915     }6916 6917     if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {6918       top += body.offsetTop;6919       left += body.offsetLeft;6920     }6921 6922     if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {6923       top += Math.max( docElem.scrollTop, body.scrollTop );6924       left += Math.max( docElem.scrollLeft, body.scrollLeft );6925     }6926 6927     return { top: top, left: left };6928   };6929 }6930 6931 jQuery.offset = {6932   initialize: function() {6933     var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0,6934       html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";6935 6936     jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );6937 6938     container.innerHTML = html;6939     body.insertBefore( container, body.firstChild );6940     innerDiv = container.firstChild;6941     checkDiv = innerDiv.firstChild;6942     td = innerDiv.nextSibling.firstChild.firstChild;6943 6944     this.doesNotAddBorder = (checkDiv.offsetTop !== 5);6945     this.doesAddBorderForTableAndCells = (td.offsetTop === 5);6946 6947     checkDiv.style.position = "fixed";6948     checkDiv.style.top = "20px";6949 6950     // safari subtracts parent border width here which is 5px6951     this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);6952     checkDiv.style.position = checkDiv.style.top = "";6953 6954     innerDiv.style.overflow = "hidden";6955     innerDiv.style.position = "relative";6956 6957     this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);6958 6959     this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);6960 6961     body.removeChild( container );6962     body = container = innerDiv = checkDiv = table = td = null;6963     jQuery.offset.initialize = jQuery.noop;6964   },6965 6966   bodyOffset: function( body ) {6967     var top = body.offsetTop,6968       left = body.offsetLeft;6969 6970     jQuery.offset.initialize();6971 6972     if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {6973       top += parseFloat( jQuery.css(body, "marginTop") ) || 0;6974       left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;6975     }6976 6977     return { top: top, left: left };6978   },6979   6980   setOffset: function( elem, options, i ) {6981     var position = jQuery.css( elem, "position" );6982 6983     // set position first, in-case top/left are set even on static elem6984     if ( position === "static" ) {6985       elem.style.position = "relative";6986     }6987 6988     var curElem = jQuery( elem ),6989       curOffset = curElem.offset(),6990       curCSSTop = jQuery.css( elem, "top" ),6991       curCSSLeft = jQuery.css( elem, "left" ),6992       calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1),6993       props = {}, curPosition = {}, curTop, curLeft;6994 6995     // need to be able to calculate position if either top or left is auto and position is absolute6996     if ( calculatePosition ) {6997       curPosition = curElem.position();6998     }6999 7000     curTop = calculatePosition ? curPosition.top : parseInt( curCSSTop, 10 ) || 0;7001     curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0;7002 7003     if ( jQuery.isFunction( options ) ) {7004       options = options.call( elem, i, curOffset );7005     }7006 7007     if (options.top != null) {7008       props.top = (options.top - curOffset.top) + curTop;7009     }7010     if (options.left != null) {7011       props.left = (options.left - curOffset.left) + curLeft;7012     }7013     7014     if ( "using" in options ) {7015       options.using.call( elem, props );7016     } else {7017       curElem.css( props );7018     }7019   }7020 };7021 7022 7023 jQuery.fn.extend({7024   position: function() {7025     if ( !this[0] ) {7026       return null;7027     }7028 7029     var elem = this[0],7030 7031     // Get *real* offsetParent7032     offsetParent = this.offsetParent(),7033 7034     // Get correct offsets7035     offset    = this.offset(),7036     parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();7037 7038     // Subtract element margins7039     // note: when an element has margin: auto the offsetLeft and marginLeft7040     // are the same in Safari causing offset.left to incorrectly be 07041     offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;7042     offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;7043 7044     // Add offsetParent borders7045     parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;7046     parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;7047 7048     // Subtract the two offsets7049     return {7050       top: offset.top - parentOffset.top,7051       left: offset.left - parentOffset.left7052     };7053   },7054 7055   offsetParent: function() {7056     return this.map(function() {7057       var offsetParent = this.offsetParent || document.body;7058       while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {7059         offsetParent = offsetParent.offsetParent;7060       }7061       return offsetParent;7062     });7063   }7064 });7065 7066 7067 // Create scrollLeft and scrollTop methods7068 jQuery.each( ["Left", "Top"], function( i, name ) {7069   var method = "scroll" + name;7070 7071   jQuery.fn[ method ] = function(val) {7072     var elem = this[0], win;7073     7074     if ( !elem ) {7075       return null;7076     }7077 7078     if ( val !== undefined ) {7079       // Set the scroll offset7080       return this.each(function() {7081         win = getWindow( this );7082 7083         if ( win ) {7084           win.scrollTo(7085             !i ? val : jQuery(win).scrollLeft(),7086             i ? val : jQuery(win).scrollTop()7087           );7088 7089         } else {7090           this[ method ] = val;7091         }7092       });7093     } else {7094       win = getWindow( elem );7095 7096       // Return the scroll offset7097       return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :7098         jQuery.support.boxModel && win.document.documentElement[ method ] ||7099           win.document.body[ method ] :7100         elem[ method ];7101     }7102   };7103 });7104 7105 function getWindow( elem ) {7106   return jQuery.isWindow( elem ) ?7107     elem :7108     elem.nodeType === 9 ?7109       elem.defaultView || elem.parentWindow :7110       false;7111 }7112 7113 7114 7115 7116 // Create innerHeight, innerWidth, outerHeight and outerWidth methods7117 jQuery.each([ "Height", "Width" ], function( i, name ) {7118 7119   var type = name.toLowerCase();7120 7121   // innerHeight and innerWidth7122   jQuery.fn["inner" + name] = function() {7123     return this[0] ?7124       parseFloat( jQuery.css( this[0], type, "padding" ) ) :7125       null;7126   };7127 7128   // outerHeight and outerWidth7129   jQuery.fn["outer" + name] = function( margin ) {7130     return this[0] ?7131       parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) :7132       null;7133   };7134 7135   jQuery.fn[ type ] = function( size ) {7136     // Get window width or height7137     var elem = this[0];7138     if ( !elem ) {7139       return size == null ? null : this;7140     }7141     7142     if ( jQuery.isFunction( size ) ) {7143       return this.each(function( i ) {7144         var self = jQuery( this );7145         self[ type ]( size.call( this, i, self[ type ]() ) );7146       });7147     }7148 7149     if ( jQuery.isWindow( elem ) ) {7150       // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode7151       return elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||7152         elem.document.body[ "client" + name ];7153 7154     // Get document width or height7155     } else if ( elem.nodeType === 9 ) {7156       // Either scroll[Width/Height] or offset[Width/Height], whichever is greater7157       return Math.max(7158         elem.documentElement["client" + name],7159         elem.body["scroll" + name], elem.documentElement["scroll" + name],7160         elem.body["offset" + name], elem.documentElement["offset" + name]7161       );7162 7163     // Get or set width or height on the element7164     } else if ( size === undefined ) {7165       var orig = jQuery.css( elem, type ),7166         ret = parseFloat( orig );7167 7168       return jQuery.isNaN( ret ) ? orig : ret;7169 7170     // Set the width or height on the element (default to pixels if value is unitless)7171     } else {7172       return this.css( type, typeof size === "string" ? size : size + "px" );7173     }7174   };7175 7176 });7177 7178 7179 })(window);

jQuery 1.4.4

 这个立即执行函数是比较庞大,所以我选取的是1.4.4这样一个比较老的版本,但也足以用来进行说明。

1.整个jQuery占用全局作用域两个变量,一个是jQuery,另一个是$。而且占用两个还是为了方便我们书写。其实两个变量是完全相同的,在第908行,我们可以看到。

// Expose jQuery to the global objectreturn (window.jQuery = window.$ = jQuery);

jQuery内部封装的变量,我们可以直接通过$来访问。这样,避免了声明不必要的全局变量。

这里的jQuery可谓起到了一个命名空间的作用。

试想,如果我们引用了另一个js插件superQuery,它占用了一个全局变量,声明window.superQuery=superQuery;

那即便superQuery内部声明了和jQuery同名变量,它们命名空间不同,实际上,并不会造成冲突。

 2.我们再来看913-1105行。

(function(){jQuery.support = {};//……})();

内部主要为创建了jQuery.support。这个创建工作只需要执行一次,所以也使用了立即执行函数。

而巧妙的是,再通过为support添加一系列的内容,就轻松将其暴露在我们可访问的范围之类了。同时,并未造成全局作用域污染。

3.参数和返回值

既然是函数,不可避免地要提一下参数和返回值。

立即函数内部是可以访问外部变量的,所以很多情况下,我们并不需要传参数。如:jQuery的window实参,如果不传入。内部也是可以直接使用的。

返回值也可以直接返回给立即执行函数外的某个变量的一个对象属性(注意,外部变量var a=1;是不能通过a.newAttribute=inParameter来赋值的。)

然而,从代码的可读性等方面考虑,我们显式地传入需要的参数是一个好习惯。

(四)注意点

立即执行函数通常作为一个单独模块使用。一般没有问题,但是,建议在自己写的立即执行函数前加分号,这样可以有效地与前面代码进行隔离。否则,可能出现意想不到的错误。

如:

    var c = 12    var d = c    (function () { var e = 14; }())

会报这样一个错误:

因为在我们立即执行函数模块前面代码没有一个分号来断句。那编译器就把前面的c和后面的语句当作函数调用来看了。

所以,由于很多时候,在立即执行函数之前的代码我们无法控制,为了良好的容错能力。我们一般在立即执行函数前加个分号与前面的代码断开,避免解析错误。