zoukankan      html  css  js  c++  java
  • 立即执行函数(IIFE)的理解与运用

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

    一、创建函数的两种方式

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

    (一)函数定义(Function Declaration)

    function Identifier ( Parameters ){ FunctionBody }

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

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

    function Identifier(Parameters){ FunctionBody }

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

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

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

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

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

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

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

    //function expression
    var myExpression = function () { return window.location }
    //function declaration
    function 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 = /^(?:[^<]*(<[wW]+>)[^>]*$|#([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 = /"[^"\
    
    ]*"|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 = /^[sxA0]+/;
     865     trimRight = /[sxA0]+$/;
     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 element
    1006     // Fails in Internet Explorer
    1007     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 any
    1019             // 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 fragments
    1033     jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
    1034 
    1035     // Figure out if the W3C box model works as expected
    1036     // document.body must exist before we can do this
    1037     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-block
    1046             // elements when setting their display to 'inline' and giving
    1047             // them layout
    1048             // (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 children
    1054             // (IE 6 does this)
    1055             div.style.display = "";
    1056             div.innerHTML = "<div style='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 set
    1064         // to display:none and there are still other visible table cells in a
    1065         // table row; if so, offsetWidth/Height are not reliable for use when
    1066         // determining if an element has been hidden directly using
    1067         // display:none (it is still safe to use offsets if a parent element is
    1068         // 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/Height
    1076         // (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 Zaytsev
    1085     // 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 IE
    1104     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 caution
    1116     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 you
    1122     // 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": true
    1128     },
    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 directly
    1148         if ( !isNode ) {
    1149             cache = elem;
    1150 
    1151         // Compute a unique ID for the element
    1152         } else if ( !id ) {
    1153             elem[ jQuery.expando ] = id = ++jQuery.uuid;
    1154         }
    1155 
    1156         // Avoid generating a new cache unless none exists and we
    1157         // 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 values
    1173         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 data
    1195         if ( name ) {
    1196             if ( thisCache ) {
    1197                 // Remove the section of cache data
    1198                 delete thisCache[ name ];
    1199 
    1200                 // If we've removed all the data, remove the element's cache
    1201                 if ( isNode && jQuery.isEmptyObject(thisCache) ) {
    1202                     jQuery.removeData( elem );
    1203                 }
    1204             }
    1205 
    1206         // Otherwise, we want to remove all of the element's data
    1207         } 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 cache
    1215             } else if ( isNode ) {
    1216                 delete cache[ id ];
    1217 
    1218             // Remove all fields from the object
    1219             } 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 expando
    1228     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 first
    1275             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 any
    1305     // data from the HTML5 data-* attribute
    1306     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 later
    1320             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 lookup
    1343         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 sentinel
    1364         if ( fn === "inprogress" ) {
    1365             fn = queue.shift();
    1366         }
    1367 
    1368         if ( fn ) {
    1369             // Add a progress sentinel to prevent the fx queue from being
    1370             // automatically dequeued
    1371             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 = /[
    	]/g,
    1429     rspaces = /s+/,
    1430     rreturn = /
    /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 names
    1546                 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 list
    1554                     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 set
    1561                     jQuery.data( this, "__className__", this.className );
    1562                 }
    1563 
    1564                 // toggle whole className
    1565                 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 but
    1588                     // uses .value. See #6932
    1589                     var val = elem.attributes.value;
    1590                     return !val || val.specified ? elem.value : elem.text;
    1591                 }
    1592 
    1593                 // We need to handle select boxes special
    1594                 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 selected
    1601                     if ( index < 0 ) {
    1602                         return null;
    1603                     }
    1604 
    1605                     // Loop through all the selected options
    1606                     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 optgroup
    1610                         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 option
    1614                             value = jQuery(option).val();
    1615 
    1616                             // We don't need an array for one selects
    1617                             if ( one ) {
    1618                                 return value;
    1619                             }
    1620 
    1621                             // Multi-Selects return an array
    1622                             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 specified
    1630                 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 value
    1636                 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 string
    1657             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          true,
    1696         height: true,
    1697         offset: true
    1698     },
    1699         
    1700     attr: function( elem, name, value, pass ) {
    1701         // don't set attributes on text and comment nodes
    1702         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 name
    1715         name = notxml && jQuery.props[ name ] || name;
    1716 
    1717         // These attributes require special treatment
    1718         var special = rspecialurl.test( name );
    1719 
    1720         // Safari mis-reports the default selected property of an option
    1721         // Accessing the parent's selectedIndex property fixes it
    1722         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 #5701
    1728                 if ( parent.parentNode ) {
    1729                     parent.parentNode.selectedIndex;
    1730                 }
    1731             }
    1732         }
    1733 
    1734         // If applicable, access the attribute via the DOM 0 way
    1735         // 'in' checks fail in Blackberry 4.7 #6931
    1736         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 set
    1759             // 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 #1070
    1783             elem.setAttribute( name, "" + value );
    1784         }
    1785 
    1786         // Ensure that missing attributes return undefined
    1787         // Blackberry 4.7 returns "" from getAttribute #6938
    1788         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 IE
    1794                 elem.getAttribute( name, 2 ) :
    1795                 elem.getAttribute( name );
    1796 
    1797         // Non-existent attributes return null, we normalize to undefined
    1798         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 = /[^ws.|`]/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 from
    1818  * Dean Edwards' addEvent library.
    1819  */
    1820 jQuery.event = {
    1821 
    1822     // Bind an event to an element
    1823     // Original by Dean Edwards
    1824     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 object
    1830         // around, causing it to be cloned in the process
    1831         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 jdalton
    1839           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 ID
    1850         if ( !handler.guid ) {
    1851             handler.guid = jQuery.guid++;
    1852         }
    1853 
    1854         // Init the element's event structure
    1855         var elemData = jQuery.data( elem );
    1856 
    1857         // If no elemData is found then we must be trying to bind to one of the
    1858         // banned noData elements
    1859         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 data
    1871             // which prevents this data from being JSON serialized
    1872             // the function does not need to be called, it just contains the data
    1873             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 holder
    1879                 // of the values to avoid JSON serialization of event data
    1880                 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 when
    1889                 // an event is called after a page has unloaded
    1890                 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 function
    1897         // 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 space
    1901         // 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 handlers
    1912             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 event
    1928             var handlers = events[ type ],
    1929                 special = jQuery.event.special[ type ] || {};
    1930 
    1931             // Init the event handler queue
    1932             if ( !handlers ) {
    1933                 handlers = events[ type ] = [];
    1934 
    1935                 // Check for a special event handler
    1936                 // Only use addEventListener/attachEvent if the special
    1937                 // events handler returns false
    1938                 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
    1939                     // Bind the global event handler to the element
    1940                     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 list
    1958             handlers.push( handleObj );
    1959 
    1960             // Keep track of which events have been used, for global triggering
    1961             jQuery.event.global[ type ] = true;
    1962         }
    1963 
    1964         // Nullify elem to prevent memory leaks in IE
    1965         elem = null;
    1966     },
    1967 
    1968     global: {},
    1969 
    1970     // Detach an event or set of events from an element
    1971     remove: function( elem, types, handler, pos ) {
    1972         // don't do events on text and comment nodes
    1973         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 here
    1996         if ( types && types.type ) {
    1997             handler = types.handler;
    1998             types = types.type;
    1999         }
    2000 
    2001         // Unbind all events for the element
    2002         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 space
    2013         // 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 handlers
    2024                 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 type
    2057                     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 exist
    2074             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 used
    2085         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 internal
    2104     trigger: function( event, data, elem /*, bubbling */ ) {
    2105         // Event object or event type
    2106         var type = event.type || event,
    2107             bubbling = arguments[3];
    2108 
    2109         if ( !bubbling ) {
    2110             event = typeof event === "object" ?
    2111                 // jQuery.Event object
    2112                 event[ jQuery.expando ] ? event :
    2113                 // Object literal
    2114                 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 trigger
    2124             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 it
    2129                 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 element
    2139 
    2140             // don't do events on text and comment nodes
    2141             if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
    2142                 return undefined;
    2143             }
    2144 
    2145             // Clean up in case it is reused
    2146             event.result = undefined;
    2147             event.target = elem;
    2148 
    2149             // Clone the incoming data, if any
    2150             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 function
    2157         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 script
    2168         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 #3533
    2177         } 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 events
    2195                         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 #3533
    2206                 } 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 handlers
    2226         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 manipulation
    2247             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 class
    2253                 if ( all || namespace_re.test( handleObj.namespace ) ) {
    2254                     // Pass in a reference to the handler function itself
    2255                     // So that we can later remove it
    2256                     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 object
    2288         // and "clone" to set read-only properties
    2289         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 necessary
    2298         if ( !event.target ) {
    2299             // Fixes #1925 where srcElement might not be defined either
    2300             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 necessary
    2309         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 available
    2314         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 events
    2323         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 === right
    2333         // Note: button is not normalized, so don't use it
    2334         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 instead
    2342     guid: 1E8,
    2343 
    2344     // Deprecated, use jQuery.proxy instead
    2345     proxy: jQuery.proxy,
    2346 
    2347     special: {
    2348         ready: {
    2349             // Make sure the ready event is setup
    2350             setup: jQuery.bindReady,
    2351             teardown: jQuery.noop
    2352         },
    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 windows
    2369                 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' keyword
    2397     if ( !this.preventDefault ) {
    2398         return new jQuery.Event( src );
    2399     }
    2400 
    2401     // Event object
    2402     if ( src && src.type ) {
    2403         this.originalEvent = src;
    2404         this.type = src.type;
    2405     // Event type
    2406     } 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 value
    2412     this.timeStamp = jQuery.now();
    2413 
    2414     // Mark it as fixed
    2415     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 Binding
    2426 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
    2427 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 event
    2437         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 event
    2453         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: returnFalse
    2466 };
    2467 
    2468 // Checks if an event happened on an element within another element
    2469 // Used in jQuery.event.special.mouseenter and mouseleave handlers
    2470 var withinElement = function( event ) {
    2471     // Check if mouse(over|out) are still within the same parent element
    2472     var parent = event.relatedTarget;
    2473 
    2474     // Firefox sometimes assigns relatedTarget a XUL element
    2475     // which we cannot access the parentNode property of
    2476     try {
    2477         // Traverse up the tree
    2478         while ( parent && parent !== this ) {
    2479             parent = parent.parentNode;
    2480         }
    2481 
    2482         if ( parent !== this ) {
    2483             // set the correct event type
    2484             event.type = event.data;
    2485 
    2486             // handle event if we actually just moused on to a non sub-element
    2487             jQuery.event.handle.apply( this, arguments );
    2488         }
    2489 
    2490     // assuming we've left the element since we most likely mousedover a xul element
    2491     } 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 events
    2502 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 delegation
    2517 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 beforeactivate
    2590         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 submit
    2620             // Keydown will be called before keypress, which is used in submit-event delegation
    2621             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 blurred
    2632             // with this event you can't trigger a change event, but you can store
    2633             // information
    2634             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()'d
    2662     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 events
    2671 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 literals
    2697         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 literals
    2730         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 closure
    2775         var args = arguments,
    2776             i = 1;
    2777 
    2778         // link all the functions, so any of them can unbind this click handler
    2779         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 execute
    2785             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 stop
    2789             event.preventDefault();
    2790 
    2791             // and execute the function
    2792             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 handler
    2855                 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 handler
    2862                 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 checking
    2917                 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 binding
    2966     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 IE
    2983 // Window isn't included so as not to unbind existing unload events
    2984 // 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 #4280
    2991                 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.0
    3002  *  Copyright 2009, The Dojo Foundation
    3003  *  Released under the MIT, BSD, and GPL Licenses.
    3004  *  More information: http://sizzlejs.com/
    3005  */
    3006 (function(){
    3007 
    3008 var chunker = /((?:((?:([^()]+)|[^()]+)+)|[(?:[[^[]]*]|['"][^'"]*['"]|[^[]'"]+)+]|\.|[^ >+~,([\]+)+|[>+~])(s*,s*)?((?:.|
    |
    )*)/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 of
    3015 // optimization where it does not always call our comparision
    3016 // 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 ID
    3083         // (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 expression
    3305         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: /#((?:[wu00c0-uFFFF-]|\.)+)/,
    3329         CLASS: /.((?:[wu00c0-uFFFF-]|\.)+)/,
    3330         NAME: /[name=['"]*((?:[wu00c0-uFFFF-]|\.)+)['"]*]/,
    3331         ATTR: /[s*((?:[wu00c0-uFFFF-]|\.)+)s*(?:(S?=)s*(['"]*)(.*?)3|)s*]/,
    3332         TAG: /^((?:[wu00c0-uFFFF*-]|\.)+)/,
    3333         CHILD: /:(only|nth|last|first)-child(?:((even|odd|[dn+-]*)))?/,
    3334         POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:((d*)))?(?=[^-]|$)/,
    3335         PSEUDO: /:((?:[wu00c0-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 returns
    3445                 // nodes that are no longer in the document #6963
    3446                 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(/[	
    ]/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 negative
    3509                 match[2] = (test[1] + (test[2] || 1)) - 0;
    3510                 match[3] = test[3] - 0;
    3511             }
    3512 
    3513             // TODO: Move to normal caching system
    3514             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 one
    3536                 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-default
    3578             // options in Safari work properly
    3579             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 (/hd/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( /(^(?:.|
    |
    )*?)/.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 of
    3838 // converting a NodeList to an array using builtin methods.
    3839 // Also verifies that the returned array holds DOM nodes
    3840 // (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 work
    3845 } 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 early
    3896         if ( a === b ) {
    3897             hasDuplicate = true;
    3898             return 0;
    3899 
    3900         // If the nodes are siblings (or identical) we can do a quick check
    3901         } else if ( aup === bup ) {
    3902             return siblingCheck( a, b );
    3903 
    3904         // If no parents were found then the nodes are disconnected
    3905         } 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 need
    3913         // to build up a full list of the parentNodes for comparison
    3914         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 discrepancy
    3930         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 check
    3937         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 nodes
    3962 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 nodes
    3969         if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
    3970             ret += elem.nodeValue;
    3971 
    3972         // Traverse everything else, except comment nodes
    3973         } 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 when
    3982 // querying by getElementById (and provide a workaround)
    3983 (function(){
    3984     // We're going to inject a fake input element with a specified name
    3985     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 quickly
    3992     root.insertBefore( form, root.firstChild );
    3993 
    3994     // The workaround has to do additional checks after a getElementById
    3995     // 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 IE
    4019     root = form = null;
    4020 })();
    4021 
    4022 (function(){
    4023     // Check to see if the browser returns only elements
    4024     // when doing getElementsByTagName("*")
    4025 
    4026     // Create a fake element
    4027     var div = document.createElement("div");
    4028     div.appendChild( document.createComment("") );
    4029 
    4030     // Make sure no comments are found
    4031     if ( div.getElementsByTagName("*").length > 0 ) {
    4032         Expr.find.TAG = function( match, context ) {
    4033             var results = context.getElementsByTagName( match[1] );
    4034 
    4035             // Filter out possible comments
    4036             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 attributes
    4053     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 IE
    4064     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 when
    4076         // 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 quoted
    4085             query = query.replace(/=s*([^'"]]*)s*]/g, "='$1']");
    4086 
    4087             // Only use querySelectorAll on non-XML documents
    4088             // (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 queries
    4096                 // We can work around this by specifying an extra ID on the root
    4097                 // and working up from there (Thanks to Andrew Dupont for the technique)
    4098                 // IE 8 doesn't work on object elements
    4099                 } 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 IE
    4127         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 exception
    4138         // Gecko does not error, returns false instead
    4139         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 quoted
    4148             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 exists
    4170     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 IE
    4189     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 exist
    4284     // (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 filter
    4297     // And so must :not(positional) so we move all PSEUDOs to the end
    4298     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 // EXPOSE
    4313 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 Sizzle
    4328     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 unique
    4344                 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 within
    4443     // the matched set of elements
    4444     index: function( elem ) {
    4445         if ( !elem || typeof elem === "string" ) {
    4446             return jQuery.inArray( this[0],
    4447                 // If it receives a string, the selector is used
    4448                 // If it receives nothing, the siblings are used
    4449                 elem ? jQuery( elem ) : this.parent().children() );
    4450         }
    4451         // Locate the position of the desired element
    4452         return jQuery.inArray(
    4453             // If it receives a jQuery object, the first element is used
    4454             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 disconnected
    4474 // 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 not
    4592 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 = / jQueryd+="(?: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 = /checkeds*(?:[^=]|=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 normally
    4650 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 around
    4680             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 document
    4775     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 leaks
    4795             if ( elem.nodeType === 1 ) {
    4796                 jQuery.cleanData( elem.getElementsByTagName("*") );
    4797             }
    4798 
    4799             // Remove any remaining nodes
    4800             while ( elem.firstChild ) {
    4801                 elem.removeChild( elem.firstChild );
    4802             }
    4803         }
    4804         
    4805         return this;
    4806     },
    4807 
    4808     clone: function( events ) {
    4809         // Do the clone
    4810         var ret = this.map(function() {
    4811             if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
    4812                 // IE copies events bound via attachEvent when
    4813                 // using cloneNode. Calling detachEvent on the
    4814                 // clone will also remove the events from the orignal
    4815                 // In order to get around this, we use innerHTML.
    4816                 // Unfortunately, this means some modifications to
    4817                 // attributes in IE that are actually only stored
    4818                 // as properties will not be copied (such as the
    4819                 // 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 tag
    4831                     .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 clone
    4839         if ( events === true ) {
    4840             cloneCopyEvent( this, ret );
    4841             cloneCopyEvent( this.find("*"), ret.find("*") );
    4842         }
    4843 
    4844         // Return the cloned set
    4845         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 innerHTML
    4855         } 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 leaks
    4864                     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 method
    4871             } 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 inserted
    4892             // this can help fix replacing a parent with child elements
    4893             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 WebKit
    4931         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 one
    4949             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                             fragment
    4975                     );
    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 document
    5025     // Cloning options loses the selected state, so don't cache them
    5026     // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
    5027     // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
    5028     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 nodes
    5103             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 browsers
    5108                 elem = elem.replace(rxhtmlTag, "<$1></$2>");
    5109 
    5110                 // Trim whitespace, otherwise indexOf won't work as expected
    5111                 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 wrappers
    5117                 div.innerHTML = wrap[1] + elem + wrap[2];
    5118 
    5119                 // Move to the right depth
    5120                 while ( depth-- ) {
    5121                     div = div.lastChild;
    5122                 }
    5123 
    5124                 // Remove IE's autoinserted <tbody> from table fragments
    5125                 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 used
    5146                 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-op
    5256     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 default
    5269     // behavior of getting and setting a style property
    5270     cssHooks: {
    5271         opacity: {
    5272             get: function( elem, computed ) {
    5273                 if ( computed ) {
    5274                     // We should always get a number back from opacity
    5275                     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 px
    5286     cssNumber: {
    5287         "zIndex": true,
    5288         "fontWeight": true,
    5289         "opacity": true,
    5290         "zoom": true,
    5291         "lineHeight": true
    5292     },
    5293 
    5294     // Add in properties whose names you wish to fix before
    5295     // setting or getting the value
    5296     cssProps: {
    5297         // normalize float css property
    5298         "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
    5299     },
    5300 
    5301     // Get and set the style property on a DOM Node
    5302     style: function( elem, name, value, extra ) {
    5303         // Don't set styles on text and comment nodes
    5304         if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
    5305             return;
    5306         }
    5307 
    5308         // Make sure that we're working with the right name
    5309         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 value
    5315         if ( value !== undefined ) {
    5316             // Make sure that NaN and null values aren't set. See: #7116
    5317             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 value
    5327             if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
    5328                 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
    5329                 // Fixes bug #5509
    5330                 try {
    5331                     style[ name ] = value;
    5332                 } catch(e) {}
    5333             }
    5334 
    5335         } else {
    5336             // If a hook was provided get the non-computed value from there
    5337             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 object
    5342             return style[ name ];
    5343         }
    5344     },
    5345 
    5346     css: function( elem, name, extra ) {
    5347         // Make sure that we're working with the right name
    5348         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 there
    5354         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 that
    5358         } 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 calculations
    5364     swap: function( elem, options, callback ) {
    5365         var old = {};
    5366 
    5367         // Remember the old values, and insert the new ones
    5368         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 values
    5376         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() instead
    5387 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 for
    5413                         // temporary backwards-compat
    5414                         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 for
    5422                     // temporary backwards-compat
    5423                     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 #1599
    5433                 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 opacity
    5450             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 layout
    5459             // Force it by setting the zoom level
    5460             style.zoom = 1;
    5461 
    5462             // Set the alpha filter to set the opacity
    5463             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 Edwards
    5503         // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
    5504 
    5505         // If we're not dealing with a regular pixel number
    5506         // but a number that has a weird ending, we need to convert it to pixels
    5507         if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
    5508             // Remember the original values
    5509             left = style.left;
    5510             rsLeft = elem.runtimeStyle.left;
    5511 
    5512             // Put in the new values to get a computed value out
    5513             elem.runtimeStyle.left = elem.currentStyle.left;
    5514             style.left = name === "fontSize" ? "1em" : (ret || 0);
    5515             ret = style.pixelLeft + "px";
    5516 
    5517             // Revert the changed values
    5518             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[^<]*(?:(?!</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 method
    5582     _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 requested
    5590         } 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 request
    5601         var type = "GET";
    5602 
    5603         // If the second parameter was provided
    5604         if ( params ) {
    5605             // If it's a function
    5606             if ( jQuery.isFunction( params ) ) {
    5607                 // We assume that it's the callback
    5608                 callback = params;
    5609                 params = null;
    5610 
    5611             // Otherwise, build a param string
    5612             } 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 document
    5621         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 elements
    5628                 if ( status === "success" || status === "notmodified" ) {
    5629                     // See if a selector was specified
    5630                     self.html( selector ?
    5631                         // Create a dummy div to hold the results
    5632                         jQuery("<div>")
    5633                             // inject the contents of the document in, removing the scripts
    5634                             // to avoid any 'Permission Denied' errors in IE
    5635                             .append(res.responseText.replace(rscript, ""))
    5636 
    5637                             // Locate the specified elements
    5638                             .find(selector) :
    5639 
    5640                         // If not, just inject the full result
    5641                         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 events
    5681 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 omited
    5690         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: type
    5702         });
    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 omited
    5715         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: type
    5727         });
    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.ajaxSetup
    5749         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 provided
    5769         s.context = origSettings && origSettings.context != null ? origSettings.context : s;
    5770 
    5771         // convert data if not already a string
    5772         if ( s.data && s.processData && typeof s.data !== "string" ) {
    5773             s.data = jQuery.param( s.data, s.traditional );
    5774         }
    5775 
    5776         // Handle JSONP Parameter Callbacks
    5777         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 function
    5789         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 data
    5793             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 sure
    5800             // that a JSONP style response is executed properly
    5801             s.dataType = "script";
    5802 
    5803             // Handle JSONP-style loading
    5804             var customJsonp = window[ jsonp ];
    5805 
    5806             window[ jsonp ] = function( tmp ) {
    5807                 if ( jQuery.isFunction( customJsonp ) ) {
    5808                     customJsonp( tmp );
    5809 
    5810                 } else {
    5811                     // Garbage collect
    5812                     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 there
    5837             var ret = s.url.replace(rts, "$1_=" + ts);
    5838 
    5839             // if nothing was replaced, add timestamp to the end
    5840             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 requests
    5844         if ( s.data && noContent ) {
    5845             s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
    5846         }
    5847 
    5848         // Watch for a new set of requests
    5849         if ( s.global && jQuery.active++ === 0 ) {
    5850             jQuery.event.trigger( "ajaxStart" );
    5851         }
    5852 
    5853         // Matches an absolute URL, and saves the domain
    5854         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 document
    5858         // and trying to load JSON or Script with a GET
    5859         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 loading
    5868             if ( !jsonp ) {
    5869                 var done = false;
    5870 
    5871                 // Attach handlers for all browsers
    5872                 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 IE
    5880                         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 injection
    5893             return undefined;
    5894         }
    5895 
    5896         var requestDone = false;
    5897 
    5898         // Create the request object
    5899         var xhr = s.xhr();
    5900 
    5901         if ( !xhr ) {
    5902             return;
    5903         }
    5904 
    5905         // Open the socket
    5906         // 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 3
    5914         try {
    5915             // Set content-type if data specified and content-body is valid for this type
    5916             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 XMLHttpRequest
    5932             // Only send the header if it's not a remote XHR
    5933             if ( !remote ) {
    5934                 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    5935             }
    5936 
    5937             // Set the Accepts header for the server, depending on the dataType
    5938             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 abort
    5944         if ( s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false ) {
    5945             // Handle the global AJAX counter
    5946             if ( s.global && jQuery.active-- === 1 ) {
    5947                 jQuery.event.trigger( "ajaxStop" );
    5948             }
    5949 
    5950             // close opended socket
    5951             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 back
    5960         var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
    5961             // The request was aborted
    5962             if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
    5963                 // Opera doesn't call onreadystatechange before this point
    5964                 // so we simulate the call
    5965                 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 out
    5975             } 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 errors
    5991                     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 notmodified
    6001                 if ( status === "success" || status === "notmodified" ) {
    6002                     // JSONP handles its own success callback
    6003                     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 handlers
    6011                 if ( !jsonp ) {
    6012                     jQuery.handleComplete( s, xhr, status, data );
    6013                 }
    6014 
    6015                 if ( isTimeout === "timeout" ) {
    6016                     xhr.abort();
    6017                 }
    6018 
    6019                 // Stop memory leaks
    6020                 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 abort
    6028         try {
    6029             var oldAbort = xhr.abort;
    6030             xhr.abort = function() {
    6031                 if ( xhr ) {
    6032                     // oldAbort has no call property in IE7 so
    6033                     // just do it this way, which works in all
    6034                     // browsers
    6035                     Function.prototype.call.call( oldAbort, xhr );
    6036                 }
    6037 
    6038                 onreadystatechange( "abort" );
    6039             };
    6040         } catch( abortError ) {}
    6041 
    6042         // Timeout checker
    6043         if ( s.async && s.timeout > 0 ) {
    6044             setTimeout(function() {
    6045                 // Check to see if the request is still happening
    6046                 if ( xhr && !requestDone ) {
    6047                     onreadystatechange( "timeout" );
    6048                 }
    6049             }, s.timeout);
    6050         }
    6051 
    6052         // Send the data
    6053         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 handlers
    6060             jQuery.handleComplete( s, xhr, status, data );
    6061         }
    6062 
    6063         // firefox 1.5 doesn't fire statechange for sync requests
    6064         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 of
    6073     // key/values into a query string
    6074     param: function( a, traditional ) {
    6075         var s = [],
    6076             add = function( key, value ) {
    6077                 // If value is a function, invoke it and return its value
    6078                 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 elements
    6090             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 older
    6096             // 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 serialization
    6103         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 its
    6117                 // numeric index to resolve deserialization ambiguity issues.
    6118                 // Note that rack (as of 1.0.0) can't currently deserialize
    6119                 // nested arrays properly, and attempting to do so may cause
    6120                 // a server error. Possible fixes are to modify rack's
    6121                 // deserialization algorithm or to provide an option or flag
    6122                 // 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 now
    6145 // Want to move this to jQuery.ajax some day
    6146 jQuery.extend({
    6147 
    6148     // Counter for holding the number of active queries
    6149     active: 0,
    6150 
    6151     // Last-Modified header cache for next request
    6152     lastModified: {},
    6153     etag: {},
    6154 
    6155     handleError: function( s, xhr, status, e ) {
    6156         // If a local callback was specified, fire it
    6157         if ( s.error ) {
    6158             s.error.call( s.context, xhr, status, e );
    6159         }
    6160 
    6161         // Fire the global callback
    6162         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 data
    6169         if ( s.success ) {
    6170             s.success.call( s.context, data, status, xhr );
    6171         }
    6172 
    6173         // Fire the global callback
    6174         if ( s.global ) {
    6175             jQuery.triggerGlobal( s, "ajaxSuccess", [xhr, s] );
    6176         }
    6177     },
    6178 
    6179     handleComplete: function( s, xhr, status ) {
    6180         // Process result
    6181         if ( s.complete ) {
    6182             s.complete.call( s.context, xhr, status );
    6183         }
    6184 
    6185         // The request was completed
    6186         if ( s.global ) {
    6187             jQuery.triggerGlobal( s, "ajaxComplete", [xhr, s] );
    6188         }
    6189 
    6190         // Handle the global AJAX counter
    6191         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 not
    6201     httpSuccess: function( xhr ) {
    6202         try {
    6203             // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
    6204             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 NotModified
    6213     httpNotModified: function( xhr, url ) {
    6214         var lastModified = xhr.getResponseHeader("Last-Modified"),
    6215             etag = xhr.getResponseHeader("Etag");
    6216 
    6217         if ( lastModified ) {
    6218             jQuery.lastModified[url] = lastModified;
    6219         }
    6220 
    6221         if ( etag ) {
    6222             jQuery.etag[url] = etag;
    6223         }
    6224 
    6225         return xhr.status === 304;
    6226     },
    6227 
    6228     httpData: function( xhr, type, s ) {
    6229         var ct = xhr.getResponseHeader("content-type") || "",
    6230             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 response
    6238         // s is checked to keep backwards compatibility
    6239         if ( s && s.dataFilter ) {
    6240             data = s.dataFilter( data, type );
    6241         }
    6242 
    6243         // The filter can actually parse the response
    6244         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 context
    6250             } 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 properly
    6262  * implement the XMLHttpRequest in IE7 (can't request local files),
    6263  * so we use the ActiveXObject when it is available
    6264  * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
    6265  * we need a fallback.
    6266  */
    6267 if ( window.ActiveXObject ) {
    6268     jQuery.ajaxSettings.xhr = function() {
    6269         if ( window.location.protocol !== "file:" ) {
    6270             try {
    6271                 return new window.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 animations
    6293         [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
    6294         // width animations
    6295         [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
    6296         // opacity animations
    6297         [ "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 is
    6313                 // being hidden by cascaded rules or not
    6314                 if ( !jQuery.data(elem, "olddisplay") && display === "none" ) {
    6315                     display = elem.style.display = "";
    6316                 }
    6317 
    6318                 // Set elements which have been overridden with display: none
    6319                 // in a stylesheet to whatever the default browser style is
    6320                 // for such an element
    6321                 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 loop
    6327             // to avoid the constant reflow
    6328             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 loop
    6355             // to avoid the constant reflow
    6356             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 function
    6365     _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 the
    6400             // test suite
    6401 
    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 out
    6422                     // Record all 3 overflow attributes because IE does not
    6423                     // change the overflow attribute when overflowX and
    6424                     // overflowY are set to the same value
    6425                     opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
    6426 
    6427                     // Set display property to inline-block for height/width
    6428                     // animations on inline elements that are having width/height
    6429                     // animated
    6430                     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 layout
    6440                             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 specialEasing
    6453                     (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 value
    6479                         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 animation
    6486                         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 compliance
    6499             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 ignored
    6512             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 last
    6516                         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 forced
    6525         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 animations
    6545 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) && easing
    6565         };
    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         // Queueing
    6571         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 value
    6609     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 size
    6618     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 another
    6628     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' function
    6651     show: function() {
    6652         // Remember where we started, so that we can go back to it later
    6653         this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
    6654         this.options.show = true;
    6655 
    6656         // Begin the animation
    6657         // Make sure that we start at a small width/height to avoid any
    6658         // flash of content
    6659         this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
    6660 
    6661         // Start by showing the element
    6662         jQuery( this.elem ).show();
    6663     },
    6664 
    6665     // Simple 'hide' function
    6666     hide: function() {
    6667         // Remember where we started, so that we can go back to it later
    6668         this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
    6669         this.options.hide = true;
    6670 
    6671         // Begin the animation
    6672         this.custom(this.cur(), 0);
    6673     },
    6674 
    6675     // Each step of an animation
    6676     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 overflow
    6694                 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 done
    6704                 if ( this.options.hide ) {
    6705                     jQuery(this.elem).hide();
    6706                 }
    6707 
    6708                 // Reset the properties, if the item has been hidden or shown
    6709                 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 function
    6716                 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 swing
    6726             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 animation
    6732             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 speed
    6765         _default: 400
    6766     },
    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 node
    6840         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;1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;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,  "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 5px
    6951         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 elem
    6984         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 absolute
    6996         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* offsetParent
    7032         offsetParent = this.offsetParent(),
    7033 
    7034         // Get correct offsets
    7035         offset       = this.offset(),
    7036         parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
    7037 
    7038         // Subtract element margins
    7039         // note: when an element has margin: auto the offsetLeft and marginLeft
    7040         // are the same in Safari causing offset.left to incorrectly be 0
    7041         offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
    7042         offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
    7043 
    7044         // Add offsetParent borders
    7045         parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
    7046         parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
    7047 
    7048         // Subtract the two offsets
    7049         return {
    7050             top:  offset.top  - parentOffset.top,
    7051             left: offset.left - parentOffset.left
    7052         };
    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 methods
    7068 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 offset
    7080             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 offset
    7097             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 methods
    7117 jQuery.each([ "Height", "Width" ], function( i, name ) {
    7118 
    7119     var type = name.toLowerCase();
    7120 
    7121     // innerHeight and innerWidth
    7122     jQuery.fn["inner" + name] = function() {
    7123         return this[0] ?
    7124             parseFloat( jQuery.css( this[0], type, "padding" ) ) :
    7125             null;
    7126     };
    7127 
    7128     // outerHeight and outerWidth
    7129     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 height
    7137         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 mode
    7151             return elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
    7152                 elem.document.body[ "client" + name ];
    7153 
    7154         // Get document width or height
    7155         } else if ( elem.nodeType === 9 ) {
    7156             // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
    7157             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 element
    7164         } 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 object
    return (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和后面的语句当作函数调用来看了。

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

  • 相关阅读:
    return关键字
    类的成员之二 :方法
    面向对象(一)
    正则表达式(一)
    Linux FTP服务器vsftpd介绍与软件包安装
    Linux SSH
    Linux telnet
    Linux firewalld
    Linux iptables nat表的使用
    Linux iptables规则的基本使用
  • 原文地址:https://www.cnblogs.com/Figgy/p/4757214.html
Copyright © 2011-2022 走看看