立即执行函数(IIFE)的理解与运用

来源:互联网 发布:vb计算圆的面积和周长 编辑:程序博客网 时间:2024/06/05 16:42

作为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='/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 notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),1711             // Whether we are setting (or getting)1712             set = value !== undefined;1713 1714         // Try to normalize/fix the name1715         name = notxml && jQuery.props[ name ] || 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) && notxml && !special ) {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 && notxml && name === "style" ) {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 && notxml && special ?1793                 // 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         contextXML = Sizzle.isXML( context ),3040         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 && !contextXML &&3085                 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {3086 3087             ret = Sizzle.find( parts.shift(), context, contextXML );3088             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, contextXML );3097 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, contextXML );3124             }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, isXML ) {3196     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, isXML );3213 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         isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );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, isXMLFilter );3257 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, isXML){3412             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, isXML );3423         },3424 3425         "~": function( checkSet, part, isXML ) {3426             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, isXML );3437         }3438     },3439 3440     find: {3441         ID: function( match, context, isXML ) {3442             if ( typeof context.getElementById !== "undefined" && !isXML ) {3443                 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, isXML ) {3471             match = " " + match[1].replace(////g, "") + " ";3472 3473             if ( isXML ) {3474                 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, isXML ) {3520             var name = match[1].replace(////g, "");3521             3522             if ( !isXML && 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, isXML ) {3998             if ( typeof context.getElementById !== "undefined" && !isXML ) {3999                 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-XML documents4088             // (ID selectors don't work in non-HTML documents)4089             if ( !seed && !Sizzle.isXML(context) ) {4090                 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.isXML( node ) ) {4151                 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, isXML ) {4183         if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {4184             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, isXML ) {4193     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 && !isXML ){4208                     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, isXML ) {4226     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 ( !isXML ) {4242                         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.isXML = function( 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.isXMLDoc = Sizzle.isXML;4319 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.isXMLDoc(this) ) {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.XMLHttpRequest();5751         },5752         accepts: {5753             xml: "application/xml, text/xml",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 XMLHttpRequest5932             // Only send the header if it's not a remote XHR5933             if ( !remote ) {5934                 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");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, XML document parse errors5991                     try {5992                         // process the data (runs the xml through httpData regardless of callback)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 XMLHttpRequest to allow aborting the request etc.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 XMLHttpRequest was successful or not6201     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 XMLHttpRequest returns NotModified6213     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             xml = type === "xml" || !type && ct.indexOf("xml") >= 0,6231             data = xml ? xhr.responseXML : xhr.responseText;6232 6233         if ( xml && data.documentElement.nodeName === "parsererror" ) {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 XMLHttpRequest in IE7 (can't request local files),6263  * so we use the ActiveXObject when it is available6264  * Additionally XMLHttpRequest can be disabled in IE7/IE8 so6265  * 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.XMLHttpRequest();6272             } catch(xhrError) {}6273         }6274 6275         try {6276             return new window.ActiveXObject("Microsoft.XMLHTTP");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和后面的语句当作函数调用来看了。

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

0 0
原创粉丝点击