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

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

 

一、创建函数的两种方式

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

 

(一)函数定义(Function Declaration)

function Identifier ( Parameters ){ FunctionBody }

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

 

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

function Identifier(Parameters){ FunctionBody }

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

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

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

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

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

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

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

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

 

二、立即执行函数

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

(一)基本结构

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

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

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

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

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

另一种也很常用:

(function(){}());

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

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

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

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

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

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

(二)使用时机

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

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

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

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

(三)实例及好处

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

   1 /*!   2  * jQuery JavaScript Library v1.4.4   3  * http://jquery.com/   4  *   5  * Copyright 2010, John Resig   6  * Dual licensed under the MIT or GPL Version 2 licenses.   7  * http://jquery.org/license   8  *   9  * Includes Sizzle.js  10  * http://sizzlejs.com/  11  * Copyright 2010, The Dojo Foundation  12  * Released under the MIT, BSD, and GPL Licenses.  13  *  14  * Date: Thu Nov 11 19:04:53 2010 -0500  15  */  16 (function( window, undefined ) {  17   18 // Use the correct document accordingly with window argument (sandbox)  19 var document = window.document;  20 var jQuery = (function() {  21   22 // Define a local copy of jQuery  23 var jQuery = function( selector, context ) {  24         // The jQuery object is actually just the init constructor 'enhanced'  25         return new jQuery.fn.init( selector, context );  26     },  27   28     // Map over jQuery in case of overwrite  29     _jQuery = window.jQuery,  30   31     // Map over the $ in case of overwrite  32     _$ = window.$,  33   34     // A central reference to the root jQuery(document)  35     rootjQuery,  36   37     // A simple way to check for HTML strings or ID strings  38     // (both of which we optimize for)  39     quickExpr = /^(?:[^<]*(<[/w/W]+>)[^>]*$|#([/w/-]+)$)/,  40   41     // Is it a simple selector  42     isSimple = /^.[^:#/[/.,]*$/,  43   44     // Check if a string has a non-whitespace character in it  45     rnotwhite = //S/,  46     rwhite = //s/,  47   48     // Used for trimming whitespace  49     trimLeft = /^/s+/,  50     trimRight = //s+$/,  51   52     // Check for non-word characters  53     rnonword = //W/,  54   55     // Check for digits  56     rdigit = //d/,  57   58     // Match a standalone tag  59     rsingleTag = /^<(/w+)/s*//?>(?:)?$/,  60   61     // JSON RegExp  62     rvalidchars = /^[/],:{}/s]*$/,  63     rvalidescape = ///(?:["////bfnrt]|u[0-9a-fA-F]{4})/g,  64     rvalidtokens = /"[^"///n/r]*"|true|false|null|-?/d+(?:/./d*)?(?:[eE][+/-]?/d+)?/g,  65     rvalidbraces = /(?:^|:|,)(?:/s*/[)+/g,  66   67     // Useragent RegExp  68     rwebkit = /(webkit)[ //]([/w.]+)/,  69     ropera = /(opera)(?:.*version)?[ //]([/w.]+)/,  70     rmsie = /(msie) ([/w.]+)/,  71     rmozilla = /(mozilla)(?:.*? rv:([/w.]+))?/,  72   73     // Keep a UserAgent string for use with jQuery.browser  74     userAgent = navigator.userAgent,  75   76     // For matching the engine and version of the browser  77     browserMatch,  78       79     // Has the ready events already been bound?  80     readyBound = false,  81       82     // The functions to execute on DOM ready  83     readyList = [],  84   85     // The ready event handler  86     DOMContentLoaded,  87   88     // Save a reference to some core methods  89     toString = Object.prototype.toString,  90     hasOwn = Object.prototype.hasOwnProperty,  91     push = Array.prototype.push,  92     slice = Array.prototype.slice,  93     trim = String.prototype.trim,  94     indexOf = Array.prototype.indexOf,  95       96     // [[Class]] -> type pairs  97     class2type = {};  98   99 jQuery.fn = jQuery.prototype = { 100     init: function( selector, context ) { 101         var match, elem, ret, doc; 102  103         // Handle $(""), $(null), or $(undefined) 104         if ( !selector ) { 105             return this; 106         } 107  108         // Handle $(DOMElement) 109         if ( selector.nodeType ) { 110             this.context = this[0] = selector; 111             this.length = 1; 112             return this; 113         } 114          115         // The body element only exists once, optimize finding it 116         if ( selector === "body" && !context && document.body ) { 117             this.context = document; 118             this[0] = document.body; 119             this.selector = "body"; 120             this.length = 1; 121             return this; 122         } 123  124         // Handle HTML strings 125         if ( typeof selector === "string" ) { 126             // Are we dealing with HTML string or an ID? 127             match = quickExpr.exec( selector ); 128  129             // Verify a match, and that no context was specified for #id 130             if ( match && (match[1] || !context) ) { 131  132                 // HANDLE: $(html) -> $(array) 133                 if ( match[1] ) { 134                     doc = (context ? context.ownerDocument || context : document); 135  136                     // If a single string is passed in and it's a single tag 137                     // just do a createElement and skip the rest 138                     ret = rsingleTag.exec( selector ); 139  140                     if ( ret ) { 141                         if ( jQuery.isPlainObject( context ) ) { 142                             selector = [ document.createElement( ret[1] ) ]; 143                             jQuery.fn.attr.call( selector, context, true ); 144  145                         } else { 146                             selector = [ doc.createElement( ret[1] ) ]; 147                         } 148  149                     } else { 150                         ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); 151                         selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; 152                     } 153                      154                     return jQuery.merge( this, selector ); 155                      156                 // HANDLE: $("#id") 157                 } else { 158                     elem = document.getElementById( match[2] ); 159  160                     // Check parentNode to catch when Blackberry 4.6 returns 161                     // nodes that are no longer in the document #6963 162                     if ( elem && elem.parentNode ) { 163                         // Handle the case where IE and Opera return items 164                         // by name instead of ID 165                         if ( elem.id !== match[2] ) { 166                             return rootjQuery.find( selector ); 167                         } 168  169                         // Otherwise, we inject the element directly into the jQuery object 170                         this.length = 1; 171                         this[0] = elem; 172                     } 173  174                     this.context = document; 175                     this.selector = selector; 176                     return this; 177                 } 178  179             // HANDLE: $("TAG") 180             } else if ( !context && !rnonword.test( selector ) ) { 181                 this.selector = selector; 182                 this.context = document; 183                 selector = document.getElementsByTagName( selector ); 184                 return jQuery.merge( this, selector ); 185  186             // HANDLE: $(expr, $(...)) 187             } else if ( !context || context.jquery ) { 188                 return (context || rootjQuery).find( selector ); 189  190             // HANDLE: $(expr, context) 191             // (which is just equivalent to: $(context).find(expr) 192             } else { 193                 return jQuery( context ).find( selector ); 194             } 195  196         // HANDLE: $(function) 197         // Shortcut for document ready 198         } else if ( jQuery.isFunction( selector ) ) { 199             return rootjQuery.ready( selector ); 200         } 201  202         if (selector.selector !== undefined) { 203             this.selector = selector.selector; 204             this.context = selector.context; 205         } 206  207         return jQuery.makeArray( selector, this ); 208     }, 209  210     // Start with an empty selector 211     selector: "", 212  213     // The current version of jQuery being used 214     jquery: "1.4.4", 215  216     // The default length of a jQuery object is 0 217     length: 0, 218  219     // The number of elements contained in the matched element set 220     size: function() { 221         return this.length; 222     }, 223  224     toArray: function() { 225         return slice.call( this, 0 ); 226     }, 227  228     // Get the Nth element in the matched element set OR 229     // Get the whole matched element set as a clean array 230     get: function( num ) { 231         return num == null ? 232  233             // Return a 'clean' array 234             this.toArray() : 235  236             // Return just the object 237             ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); 238     }, 239  240     // Take an array of elements and push it onto the stack 241     // (returning the new matched element set) 242     pushStack: function( elems, name, selector ) { 243         // Build a new jQuery matched element set 244         var ret = jQuery(); 245  246         if ( jQuery.isArray( elems ) ) { 247             push.apply( ret, elems ); 248          249         } else { 250             jQuery.merge( ret, elems ); 251         } 252  253         // Add the old object onto the stack (as a reference) 254         ret.prevObject = this; 255  256         ret.context = this.context; 257  258         if ( name === "find" ) { 259             ret.selector = this.selector + (this.selector ? " " : "") + selector; 260         } else if ( name ) { 261             ret.selector = this.selector + "." + name + "(" + selector + ")"; 262         } 263  264         // Return the newly-formed element set 265         return ret; 266     }, 267  268     // Execute a callback for every element in the matched set. 269     // (You can seed the arguments with an array of args, but this is 270     // only used internally.) 271     each: function( callback, args ) { 272         return jQuery.each( this, callback, args ); 273     }, 274      275     ready: function( fn ) { 276         // Attach the listeners 277         jQuery.bindReady(); 278  279         // If the DOM is already ready 280         if ( jQuery.isReady ) { 281             // Execute the function immediately 282             fn.call( document, jQuery ); 283  284         // Otherwise, remember the function for later 285         } else if ( readyList ) { 286             // Add the function to the wait list 287             readyList.push( fn ); 288         } 289  290         return this; 291     }, 292      293     eq: function( i ) { 294         return i === -1 ? 295             this.slice( i ) : 296             this.slice( i, +i + 1 ); 297     }, 298  299     first: function() { 300         return this.eq( 0 ); 301     }, 302  303     last: function() { 304         return this.eq( -1 ); 305     }, 306  307     slice: function() { 308         return this.pushStack( slice.apply( this, arguments ), 309             "slice", slice.call(arguments).join(",") ); 310     }, 311  312     map: function( callback ) { 313         return this.pushStack( jQuery.map(this, function( elem, i ) { 314             return callback.call( elem, i, elem ); 315         })); 316     }, 317      318     end: function() { 319         return this.prevObject || jQuery(null); 320     }, 321  322     // For internal use only. 323     // Behaves like an Array's method, not like a jQuery method. 324     push: push, 325     sort: [].sort, 326     splice: [].splice 327 }; 328  329 // Give the init function the jQuery prototype for later instantiation 330 jQuery.fn.init.prototype = jQuery.fn; 331  332 jQuery.extend = jQuery.fn.extend = function() { 333      var options, name, src, copy, copyIsArray, clone, 334         target = arguments[0] || {}, 335         i = 1, 336         length = arguments.length, 337         deep = false; 338  339     // Handle a deep copy situation 340     if ( typeof target === "boolean" ) { 341         deep = target; 342         target = arguments[1] || {}; 343         // skip the boolean and the target 344         i = 2; 345     } 346  347     // Handle case when target is a string or something (possible in deep copy) 348     if ( typeof target !== "object" && !jQuery.isFunction(target) ) { 349         target = {}; 350     } 351  352     // extend jQuery itself if only one argument is passed 353     if ( length === i ) { 354         target = this; 355         --i; 356     } 357  358     for ( ; i < length; i++ ) { 359         // Only deal with non-null/undefined values 360         if ( (options = arguments[ i ]) != null ) { 361             // Extend the base object 362             for ( name in options ) { 363                 src = target[ name ]; 364                 copy = options[ name ]; 365  366                 // Prevent never-ending loop 367                 if ( target === copy ) { 368                     continue; 369                 } 370  371                 // Recurse if we're merging plain objects or arrays 372                 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { 373                     if ( copyIsArray ) { 374                         copyIsArray = false; 375                         clone = src && jQuery.isArray(src) ? src : []; 376  377                     } else { 378                         clone = src && jQuery.isPlainObject(src) ? src : {}; 379                     } 380  381                     // Never move original objects, clone them 382                     target[ name ] = jQuery.extend( deep, clone, copy ); 383  384                 // Don't bring in undefined values 385                 } else if ( copy !== undefined ) { 386                     target[ name ] = copy; 387                 } 388             } 389         } 390     } 391  392     // Return the modified object 393     return target; 394 }; 395  396 jQuery.extend({ 397     noConflict: function( deep ) { 398         window.$ = _$; 399  400         if ( deep ) { 401             window.jQuery = _jQuery; 402         } 403  404         return jQuery; 405     }, 406      407     // Is the DOM ready to be used? Set to true once it occurs. 408     isReady: false, 409  410     // A counter to track how many items to wait for before 411     // the ready event fires. See #6781 412     readyWait: 1, 413      414     // Handle when the DOM is ready 415     ready: function( wait ) { 416         // A third-party is pushing the ready event forwards 417         if ( wait === true ) { 418             jQuery.readyWait--; 419         } 420  421         // Make sure that the DOM is not already loaded 422         if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { 423             // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). 424             if ( !document.body ) { 425                 return setTimeout( jQuery.ready, 1 ); 426             } 427  428             // Remember that the DOM is ready 429             jQuery.isReady = true; 430  431             // If a normal DOM Ready event fired, decrement, and wait if need be 432             if ( wait !== true && --jQuery.readyWait > 0 ) { 433                 return; 434             } 435  436             // If there are functions bound, to execute 437             if ( readyList ) { 438                 // Execute all of them 439                 var fn, 440                     i = 0, 441                     ready = readyList; 442  443                 // Reset the list of functions 444                 readyList = null; 445  446                 while ( (fn = ready[ i++ ]) ) { 447                     fn.call( document, jQuery ); 448                 } 449  450                 // Trigger any bound ready events 451                 if ( jQuery.fn.trigger ) { 452                     jQuery( document ).trigger( "ready" ).unbind( "ready" ); 453                 } 454             } 455         } 456     }, 457      458     bindReady: function() { 459         if ( readyBound ) { 460             return; 461         } 462  463         readyBound = true; 464  465         // Catch cases where $(document).ready() is called after the 466         // browser event has already occurred. 467         if ( document.readyState === "complete" ) { 468             // Handle it asynchronously to allow scripts the opportunity to delay ready 469             return setTimeout( jQuery.ready, 1 ); 470         } 471  472         // Mozilla, Opera and webkit nightlies currently support this event 473         if ( document.addEventListener ) { 474             // Use the handy event callback 475             document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); 476              477             // A fallback to window.onload, that will always work 478             window.addEventListener( "load", jQuery.ready, false ); 479  480         // If IE event model is used 481         } else if ( document.attachEvent ) { 482             // ensure firing before onload, 483             // maybe late but safe also for iframes 484             document.attachEvent("onreadystatechange", DOMContentLoaded); 485              486             // A fallback to window.onload, that will always work 487             window.attachEvent( "onload", jQuery.ready ); 488  489             // If IE and not a frame 490             // continually check to see if the document is ready 491             var toplevel = false; 492  493             try { 494                 toplevel = window.frameElement == null; 495             } catch(e) {} 496  497             if ( document.documentElement.doScroll && toplevel ) { 498                 doScrollCheck(); 499             } 500         } 501     }, 502  503     // See test/unit/core.js for details concerning isFunction. 504     // Since version 1.3, DOM methods and functions like alert 505     // aren't supported. They return false on IE (#2968). 506     isFunction: function( obj ) { 507         return jQuery.type(obj) === "function"; 508     }, 509  510     isArray: Array.isArray || function( obj ) { 511         return jQuery.type(obj) === "array"; 512     }, 513  514     // A crude way of determining if an object is a window 515     isWindow: function( obj ) { 516         return obj && typeof obj === "object" && "setInterval" in obj; 517     }, 518  519     isNaN: function( obj ) { 520         return obj == null || !rdigit.test( obj ) || isNaN( obj ); 521     }, 522  523     type: function( obj ) { 524         return obj == null ? 525             String( obj ) : 526             class2type[ toString.call(obj) ] || "object"; 527     }, 528  529     isPlainObject: function( obj ) { 530         // Must be an Object. 531         // Because of IE, we also have to check the presence of the constructor property. 532         // Make sure that DOM nodes and window objects don't pass through, as well 533         if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { 534             return false; 535         } 536          537         // Not own constructor property must be Object 538         if ( obj.constructor && 539             !hasOwn.call(obj, "constructor") && 540             !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { 541             return false; 542         } 543          544         // Own properties are enumerated firstly, so to speed up, 545         // if last one is own, then all properties are own. 546      547         var key; 548         for ( key in obj ) {} 549          550         return key === undefined || hasOwn.call( obj, key ); 551     }, 552  553     isEmptyObject: function( obj ) { 554         for ( var name in obj ) { 555             return false; 556         } 557         return true; 558     }, 559      560     error: function( msg ) { 561         throw msg; 562     }, 563      564     parseJSON: function( data ) { 565         if ( typeof data !== "string" || !data ) { 566             return null; 567         } 568  569         // Make sure leading/trailing whitespace is removed (IE can't handle it) 570         data = jQuery.trim( data ); 571          572         // Make sure the incoming data is actual JSON 573         // Logic borrowed from http://json.org/json2.js 574         if ( rvalidchars.test(data.replace(rvalidescape, "@") 575             .replace(rvalidtokens, "]") 576             .replace(rvalidbraces, "")) ) { 577  578             // Try to use the native JSON parser first 579             return window.JSON && window.JSON.parse ? 580                 window.JSON.parse( data ) : 581                 (new Function("return " + data))(); 582  583         } else { 584             jQuery.error( "Invalid JSON: " + data ); 585         } 586     }, 587  588     noop: function() {}, 589  590     // Evalulates a script in a global context 591     globalEval: function( data ) { 592         if ( data && rnotwhite.test(data) ) { 593             // Inspired by code by Andrea Giammarchi 594             // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html 595             var head = document.getElementsByTagName("head")[0] || document.documentElement, 596                 script = document.createElement("script"); 597  598             script.type = "text/javascript"; 599  600             if ( jQuery.support.scriptEval ) { 601                 script.appendChild( document.createTextNode( data ) ); 602             } else { 603                 script.text = data; 604             } 605  606             // Use insertBefore instead of appendChild to circumvent an IE6 bug. 607             // This arises when a base node is used (#2709). 608             head.insertBefore( script, head.firstChild ); 609             head.removeChild( script ); 610         } 611     }, 612  613     nodeName: function( elem, name ) { 614         return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); 615     }, 616  617     // args is for internal usage only 618     each: function( object, callback, args ) { 619         var name, i = 0, 620             length = object.length, 621             isObj = length === undefined || jQuery.isFunction(object); 622  623         if ( args ) { 624             if ( isObj ) { 625                 for ( name in object ) { 626                     if ( callback.apply( object[ name ], args ) === false ) { 627                         break; 628                     } 629                 } 630             } else { 631                 for ( ; i < length; ) { 632                     if ( callback.apply( object[ i++ ], args ) === false ) { 633                         break; 634                     } 635                 } 636             } 637  638         // A special, fast, case for the most common use of each 639         } else { 640             if ( isObj ) { 641                 for ( name in object ) { 642                     if ( callback.call( object[ name ], name, object[ name ] ) === false ) { 643                         break; 644                     } 645                 } 646             } else { 647                 for ( var value = object[0]; 648                     i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} 649             } 650         } 651  652         return object; 653     }, 654  655     // Use native String.trim function wherever possible 656     trim: trim ? 657         function( text ) { 658             return text == null ? 659                 "" : 660                 trim.call( text ); 661         } : 662  663         // Otherwise use our own trimming functionality 664         function( text ) { 665             return text == null ? 666                 "" : 667                 text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); 668         }, 669  670     // results is for internal usage only 671     makeArray: function( array, results ) { 672         var ret = results || []; 673  674         if ( array != null ) { 675             // The window, strings (and functions) also have 'length' 676             // The extra typeof function check is to prevent crashes 677             // in Safari 2 (See: #3039) 678             // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 679             var type = jQuery.type(array); 680  681             if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { 682                 push.call( ret, array ); 683             } else { 684                 jQuery.merge( ret, array ); 685             } 686         } 687  688         return ret; 689     }, 690  691     inArray: function( elem, array ) { 692         if ( array.indexOf ) { 693             return array.indexOf( elem ); 694         } 695  696         for ( var i = 0, length = array.length; i < length; i++ ) { 697             if ( array[ i ] === elem ) { 698                 return i; 699             } 700         } 701  702         return -1; 703     }, 704  705     merge: function( first, second ) { 706         var i = first.length, 707             j = 0; 708  709         if ( typeof second.length === "number" ) { 710             for ( var l = second.length; j < l; j++ ) { 711                 first[ i++ ] = second[ j ]; 712             } 713          714         } else { 715             while ( second[j] !== undefined ) { 716                 first[ i++ ] = second[ j++ ]; 717             } 718         } 719  720         first.length = i; 721  722         return first; 723     }, 724  725     grep: function( elems, callback, inv ) { 726         var ret = [], retVal; 727         inv = !!inv; 728  729         // Go through the array, only saving the items 730         // that pass the validator function 731         for ( var i = 0, length = elems.length; i < length; i++ ) { 732             retVal = !!callback( elems[ i ], i ); 733             if ( inv !== retVal ) { 734                 ret.push( elems[ i ] ); 735             } 736         } 737  738         return ret; 739     }, 740  741     // arg is for internal usage only 742     map: function( elems, callback, arg ) { 743         var ret = [], value; 744  745         // Go through the array, translating each of the items to their 746         // new value (or values). 747         for ( var i = 0, length = elems.length; i < length; i++ ) { 748             value = callback( elems[ i ], i, arg ); 749  750             if ( value != null ) { 751                 ret[ ret.length ] = value; 752             } 753         } 754  755         return ret.concat.apply( [], ret ); 756     }, 757  758     // A global GUID counter for objects 759     guid: 1, 760  761     proxy: function( fn, proxy, thisObject ) { 762         if ( arguments.length === 2 ) { 763             if ( typeof proxy === "string" ) { 764                 thisObject = fn; 765                 fn = thisObject[ proxy ]; 766                 proxy = undefined; 767  768             } else if ( proxy && !jQuery.isFunction( proxy ) ) { 769                 thisObject = proxy; 770                 proxy = undefined; 771             } 772         } 773  774         if ( !proxy && fn ) { 775             proxy = function() { 776                 return fn.apply( thisObject || this, arguments ); 777             }; 778         } 779  780         // Set the guid of unique handler to the same of original handler, so it can be removed 781         if ( fn ) { 782             proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; 783         } 784  785         // So proxy can be declared as an argument 786         return proxy; 787     }, 788  789     // Mutifunctional method to get and set values to a collection 790     // The value/s can be optionally by executed if its a function 791     access: function( elems, key, value, exec, fn, pass ) { 792         var length = elems.length; 793      794         // Setting many attributes 795         if ( typeof key === "object" ) { 796             for ( var k in key ) { 797                 jQuery.access( elems, k, key[k], exec, fn, value ); 798             } 799             return elems; 800         } 801      802         // Setting one attribute 803         if ( value !== undefined ) { 804             // Optionally, function values get executed if exec is true 805             exec = !pass && exec && jQuery.isFunction(value); 806          807             for ( var i = 0; i < length; i++ ) { 808                 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); 809             } 810          811             return elems; 812         } 813      814         // Getting an attribute 815         return length ? fn( elems[0], key ) : undefined; 816     }, 817  818     now: function() { 819         return (new Date()).getTime(); 820     }, 821  822     // Use of jQuery.browser is frowned upon. 823     // More details: http://docs.jquery.com/Utilities/jQuery.browser 824     uaMatch: function( ua ) { 825         ua = ua.toLowerCase(); 826  827         var match = rwebkit.exec( ua ) || 828             ropera.exec( ua ) || 829             rmsie.exec( ua ) || 830             ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || 831             []; 832  833         return { browser: match[1] || "", version: match[2] || "0" }; 834     }, 835  836     browser: {} 837 }); 838  839 // Populate the class2type map 840 jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { 841     class2type[ "[object " + name + "]" ] = name.toLowerCase(); 842 }); 843  844 browserMatch = jQuery.uaMatch( userAgent ); 845 if ( browserMatch.browser ) { 846     jQuery.browser[ browserMatch.browser ] = true; 847     jQuery.browser.version = browserMatch.version; 848 } 849  850 // Deprecated, use jQuery.browser.webkit instead 851 if ( jQuery.browser.webkit ) { 852     jQuery.browser.safari = true; 853 } 854  855 if ( indexOf ) { 856     jQuery.inArray = function( elem, array ) { 857         return indexOf.call( array, elem ); 858     }; 859 } 860  861 // Verify that /s matches non-breaking spaces 862 // (IE fails on this test) 863 if ( !rwhite.test( "/xA0" ) ) { 864     trimLeft = /^[/s/xA0]+/; 865     trimRight = /[/s/xA0]+$/; 866 } 867  868 // All jQuery objects should point back to these 869 rootjQuery = jQuery(document); 870  871 // Cleanup functions for the document ready method 872 if ( document.addEventListener ) { 873     DOMContentLoaded = function() { 874         document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); 875         jQuery.ready(); 876     }; 877  878 } else if ( document.attachEvent ) { 879     DOMContentLoaded = function() { 880         // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). 881         if ( document.readyState === "complete" ) { 882             document.detachEvent( "onreadystatechange", DOMContentLoaded ); 883             jQuery.ready(); 884         } 885     }; 886 } 887  888 // The DOM ready check for Internet Explorer 889 function doScrollCheck() { 890     if ( jQuery.isReady ) { 891         return; 892     } 893  894     try { 895         // If IE is used, use the trick by Diego Perini 896         // http://javascript.nwbox.com/IEContentLoaded/ 897         document.documentElement.doScroll("left"); 898     } catch(e) { 899         setTimeout( doScrollCheck, 1 ); 900         return; 901     } 902  903     // and execute any waiting functions 904     jQuery.ready(); 905 } 906  907 // Expose jQuery to the global object 908 return (window.jQuery = window.$ = jQuery); 909  910 })(); 911  912  913 (function() { 914  915     jQuery.support = {}; 916  917     var root = document.documentElement, 918         script = document.createElement("script"), 919         div = document.createElement("div"), 920         id = "script" + jQuery.now(); 921  922     div.style.display = "none"; 923     div.innerHTML = "   
a"; 924 925 var all = div.getElementsByTagName("*"), 926 a = div.getElementsByTagName("a")[0], 927 select = document.createElement("select"), 928 opt = select.appendChild( document.createElement("option") ); 929 930 // Can't get basic test support 931 if ( !all || !all.length || !a ) { 932 return; 933 } 934 935 jQuery.support = { 936 // IE strips leading whitespace when .innerHTML is used 937 leadingWhitespace: div.firstChild.nodeType === 3, 938 939 // Make sure that tbody elements aren't automatically inserted 940 // IE will insert them into empty tables 941 tbody: !div.getElementsByTagName("tbody").length, 942 943 // Make sure that link elements get serialized correctly by innerHTML 944 // This requires a wrapper element in IE 945 htmlSerialize: !!div.getElementsByTagName("link").length, 946 947 // Get the style information from getAttribute 948 // (IE uses .cssText insted) 949 style: /red/.test( a.getAttribute("style") ), 950 951 // Make sure that URLs aren't manipulated 952 // (IE normalizes it by default) 953 hrefNormalized: a.getAttribute("href") === "/a", 954 955 // Make sure that element opacity exists 956 // (IE uses filter instead) 957 // Use a regex to work around a WebKit issue. See #5145 958 opacity: /^0.55$/.test( a.style.opacity ), 959 960 // Verify style float existence 961 // (IE uses styleFloat instead of cssFloat) 962 cssFloat: !!a.style.cssFloat, 963 964 // Make sure that if no value is specified for a checkbox 965 // that it defaults to "on". 966 // (WebKit defaults to "" instead) 967 checkOn: div.getElementsByTagName("input")[0].value === "on", 968 969 // Make sure that a selected-by-default option has a working selected property. 970 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) 971 optSelected: opt.selected, 972 973 // Will be defined later 974 deleteExpando: true, 975 optDisabled: false, 976 checkClone: false, 977 scriptEval: false, 978 noCloneEvent: true, 979 boxModel: null, 980 inlineBlockNeedsLayout: false, 981 shrinkWrapBlocks: false, 982 reliableHiddenOffsets: true 983 }; 984 985 // Make sure that the options inside disabled selects aren't marked as disabled 986 // (WebKit marks them as diabled) 987 select.disabled = true; 988 jQuery.support.optDisabled = !opt.disabled; 989 990 script.type = "text/javascript"; 991 try { 992 script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); 993 } catch(e) {} 994 995 root.insertBefore( script, root.firstChild ); 996 997 // Make sure that the execution of code works by injecting a script 998 // tag with appendChild/createTextNode 999 // (IE doesn't support this, fails, and uses .text instead)1000 if ( window[ id ] ) {1001 jQuery.support.scriptEval = true;1002 delete window[ id ];1003 }1004 1005 // Test to see if it's possible to delete an expando from an element1006 // Fails in Internet Explorer1007 try {1008 delete script.test;1009 1010 } catch(e) {1011 jQuery.support.deleteExpando = false;1012 }1013 1014 root.removeChild( script );1015 1016 if ( div.attachEvent && div.fireEvent ) {1017 div.attachEvent("onclick", function click() {1018 // Cloning a node shouldn't copy over any1019 // bound event handlers (IE does this)1020 jQuery.support.noCloneEvent = false;1021 div.detachEvent("onclick", click);1022 });1023 div.cloneNode(true).fireEvent("onclick");1024 }1025 1026 div = document.createElement("div");1027 div.innerHTML = "";1028 1029 var fragment = document.createDocumentFragment();1030 fragment.appendChild( div.firstChild );1031 1032 // WebKit doesn't clone checked state correctly in fragments1033 jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;1034 1035 // Figure out if the W3C box model works as expected1036 // document.body must exist before we can do this1037 jQuery(function() {1038 var div = document.createElement("div");1039 div.style.width = div.style.paddingLeft = "1px";1040 1041 document.body.appendChild( div );1042 jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;1043 1044 if ( "zoom" in div.style ) {1045 // Check if natively block-level elements act like inline-block1046 // elements when setting their display to 'inline' and giving1047 // them layout1048 // (IE < 8 does this)1049 div.style.display = "inline";1050 div.style.zoom = 1;1051 jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2;1052 1053 // Check if elements with layout shrink-wrap their children1054 // (IE 6 does this)1055 div.style.display = "";1056 div.innerHTML = "
";1057 jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;1058 }1059 1060 div.innerHTML = "
t
";1061 var tds = div.getElementsByTagName("td");1062 1063 // Check if table cells still have offsetWidth/Height when they are set1064 // to display:none and there are still other visible table cells in a1065 // table row; if so, offsetWidth/Height are not reliable for use when1066 // determining if an element has been hidden directly using1067 // display:none (it is still safe to use offsets if a parent element is1068 // hidden; don safety goggles and see bug #4512 for more information).1069 // (only IE 8 fails this test)1070 jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0;1071 1072 tds[0].style.display = "";1073 tds[1].style.display = "none";1074 1075 // Check if empty table cells still have offsetWidth/Height1076 // (IE < 8 fail this test)1077 jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0;1078 div.innerHTML = "";1079 1080 document.body.removeChild( div ).style.display = "none";1081 div = tds = null;1082 });1083 1084 // Technique from Juriy Zaytsev1085 // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/1086 var eventSupported = function( eventName ) {1087 var el = document.createElement("div");1088 eventName = "on" + eventName;1089 1090 var isSupported = (eventName in el);1091 if ( !isSupported ) {1092 el.setAttribute(eventName, "return;");1093 isSupported = typeof el[eventName] === "function";1094 }1095 el = null;1096 1097 return isSupported;1098 };1099 1100 jQuery.support.submitBubbles = eventSupported("submit");1101 jQuery.support.changeBubbles = eventSupported("change");1102 1103 // release memory in IE1104 root = script = div = all = a = null;1105 })();1106 1107 1108 1109 var windowData = {},1110 rbrace = /^(?:/{.*/}|/[.*/])$/;1111 1112 jQuery.extend({1113 cache: {},1114 1115 // Please use with caution1116 uuid: 0,1117 1118 // Unique for each copy of jQuery on the page 1119 expando: "jQuery" + jQuery.now(),1120 1121 // The following elements throw uncatchable exceptions if you1122 // attempt to add expando properties to them.1123 noData: {1124 "embed": true,1125 // Ban all objects except for Flash (which handle expandos)1126 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",1127 "applet": true1128 },1129 1130 data: function( elem, name, data ) {1131 if ( !jQuery.acceptData( elem ) ) {1132 return;1133 }1134 1135 elem = elem == window ?1136 windowData :1137 elem;1138 1139 var isNode = elem.nodeType,1140 id = isNode ? elem[ jQuery.expando ] : null,1141 cache = jQuery.cache, thisCache;1142 1143 if ( isNode && !id && typeof name === "string" && data === undefined ) {1144 return;1145 }1146 1147 // Get the data from the object directly1148 if ( !isNode ) {1149 cache = elem;1150 1151 // Compute a unique ID for the element1152 } else if ( !id ) {1153 elem[ jQuery.expando ] = id = ++jQuery.uuid;1154 }1155 1156 // Avoid generating a new cache unless none exists and we1157 // want to manipulate it.1158 if ( typeof name === "object" ) {1159 if ( isNode ) {1160 cache[ id ] = jQuery.extend(cache[ id ], name);1161 1162 } else {1163 jQuery.extend( cache, name );1164 }1165 1166 } else if ( isNode && !cache[ id ] ) {1167 cache[ id ] = {};1168 }1169 1170 thisCache = isNode ? cache[ id ] : cache;1171 1172 // Prevent overriding the named cache with undefined values1173 if ( data !== undefined ) {1174 thisCache[ name ] = data;1175 }1176 1177 return typeof name === "string" ? thisCache[ name ] : thisCache;1178 },1179 1180 removeData: function( elem, name ) {1181 if ( !jQuery.acceptData( elem ) ) {1182 return;1183 }1184 1185 elem = elem == window ?1186 windowData :1187 elem;1188 1189 var isNode = elem.nodeType,1190 id = isNode ? elem[ jQuery.expando ] : elem,1191 cache = jQuery.cache,1192 thisCache = isNode ? cache[ id ] : id;1193 1194 // If we want to remove a specific section of the element's data1195 if ( name ) {1196 if ( thisCache ) {1197 // Remove the section of cache data1198 delete thisCache[ name ];1199 1200 // If we've removed all the data, remove the element's cache1201 if ( isNode && jQuery.isEmptyObject(thisCache) ) {1202 jQuery.removeData( elem );1203 }1204 }1205 1206 // Otherwise, we want to remove all of the element's data1207 } else {1208 if ( isNode && jQuery.support.deleteExpando ) {1209 delete elem[ jQuery.expando ];1210 1211 } else if ( elem.removeAttribute ) {1212 elem.removeAttribute( jQuery.expando );1213 1214 // Completely remove the data cache1215 } else if ( isNode ) {1216 delete cache[ id ];1217 1218 // Remove all fields from the object1219 } else {1220 for ( var n in elem ) {1221 delete elem[ n ];1222 }1223 }1224 }1225 },1226 1227 // A method for determining if a DOM node can handle the data expando1228 acceptData: function( elem ) {1229 if ( elem.nodeName ) {1230 var match = jQuery.noData[ elem.nodeName.toLowerCase() ];1231 1232 if ( match ) {1233 return !(match === true || elem.getAttribute("classid") !== match);1234 }1235 }1236 1237 return true;1238 }1239 });1240 1241 jQuery.fn.extend({1242 data: function( key, value ) {1243 var data = null;1244 1245 if ( typeof key === "undefined" ) {1246 if ( this.length ) {1247 var attr = this[0].attributes, name;1248 data = jQuery.data( this[0] );1249 1250 for ( var i = 0, l = attr.length; i < l; i++ ) {1251 name = attr[i].name;1252 1253 if ( name.indexOf( "data-" ) === 0 ) {1254 name = name.substr( 5 );1255 dataAttr( this[0], name, data[ name ] );1256 }1257 }1258 }1259 1260 return data;1261 1262 } else if ( typeof key === "object" ) {1263 return this.each(function() {1264 jQuery.data( this, key );1265 });1266 }1267 1268 var parts = key.split(".");1269 parts[1] = parts[1] ? "." + parts[1] : "";1270 1271 if ( value === undefined ) {1272 data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);1273 1274 // Try to fetch any internally stored data first1275 if ( data === undefined && this.length ) {1276 data = jQuery.data( this[0], key );1277 data = dataAttr( this[0], key, data );1278 }1279 1280 return data === undefined && parts[1] ?1281 this.data( parts[0] ) :1282 data;1283 1284 } else {1285 return this.each(function() {1286 var $this = jQuery( this ),1287 args = [ parts[0], value ];1288 1289 $this.triggerHandler( "setData" + parts[1] + "!", args );1290 jQuery.data( this, key, value );1291 $this.triggerHandler( "changeData" + parts[1] + "!", args );1292 });1293 }1294 },1295 1296 removeData: function( key ) {1297 return this.each(function() {1298 jQuery.removeData( this, key );1299 });1300 }1301 });1302 1303 function dataAttr( elem, key, data ) {1304 // If nothing was found internally, try to fetch any1305 // data from the HTML5 data-* attribute1306 if ( data === undefined && elem.nodeType === 1 ) {1307 data = elem.getAttribute( "data-" + key );1308 1309 if ( typeof data === "string" ) {1310 try {1311 data = data === "true" ? true :1312 data === "false" ? false :1313 data === "null" ? null :1314 !jQuery.isNaN( data ) ? parseFloat( data ) :1315 rbrace.test( data ) ? jQuery.parseJSON( data ) :1316 data;1317 } catch( e ) {}1318 1319 // Make sure we set the data so it isn't changed later1320 jQuery.data( elem, key, data );1321 1322 } else {1323 data = undefined;1324 }1325 }1326 1327 return data;1328 }1329 1330 1331 1332 1333 jQuery.extend({1334 queue: function( elem, type, data ) {1335 if ( !elem ) {1336 return;1337 }1338 1339 type = (type || "fx") + "queue";1340 var q = jQuery.data( elem, type );1341 1342 // Speed up dequeue by getting out quickly if this is just a lookup1343 if ( !data ) {1344 return q || [];1345 }1346 1347 if ( !q || jQuery.isArray(data) ) {1348 q = jQuery.data( elem, type, jQuery.makeArray(data) );1349 1350 } else {1351 q.push( data );1352 }1353 1354 return q;1355 },1356 1357 dequeue: function( elem, type ) {1358 type = type || "fx";1359 1360 var queue = jQuery.queue( elem, type ),1361 fn = queue.shift();1362 1363 // If the fx queue is dequeued, always remove the progress sentinel1364 if ( fn === "inprogress" ) {1365 fn = queue.shift();1366 }1367 1368 if ( fn ) {1369 // Add a progress sentinel to prevent the fx queue from being1370 // automatically dequeued1371 if ( type === "fx" ) {1372 queue.unshift("inprogress");1373 }1374 1375 fn.call(elem, function() {1376 jQuery.dequeue(elem, type);1377 });1378 }1379 }1380 });1381 1382 jQuery.fn.extend({1383 queue: function( type, data ) {1384 if ( typeof type !== "string" ) {1385 data = type;1386 type = "fx";1387 }1388 1389 if ( data === undefined ) {1390 return jQuery.queue( this[0], type );1391 }1392 return this.each(function( i ) {1393 var queue = jQuery.queue( this, type, data );1394 1395 if ( type === "fx" && queue[0] !== "inprogress" ) {1396 jQuery.dequeue( this, type );1397 }1398 });1399 },1400 dequeue: function( type ) {1401 return this.each(function() {1402 jQuery.dequeue( this, type );1403 });1404 },1405 1406 // Based off of the plugin by Clint Helfers, with permission.1407 // http://blindsignals.com/index.php/2009/07/jquery-delay/1408 delay: function( time, type ) {1409 time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;1410 type = type || "fx";1411 1412 return this.queue( type, function() {1413 var elem = this;1414 setTimeout(function() {1415 jQuery.dequeue( elem, type );1416 }, time );1417 });1418 },1419 1420 clearQueue: function( type ) {1421 return this.queue( type || "fx", [] );1422 }1423 });1424 1425 1426 1427 1428 var rclass = /[/n/t]/g,1429 rspaces = //s+/,1430 rreturn = //r/g,1431 rspecialurl = /^(?:href|src|style)$/,1432 rtype = /^(?:button|input)$/i,1433 rfocusable = /^(?:button|input|object|select|textarea)$/i,1434 rclickable = /^a(?:rea)?$/i,1435 rradiocheck = /^(?:radio|checkbox)$/i;1436 1437 jQuery.props = {1438 "for": "htmlFor",1439 "class": "className",1440 readonly: "readOnly",1441 maxlength: "maxLength",1442 cellspacing: "cellSpacing",1443 rowspan: "rowSpan",1444 colspan: "colSpan",1445 tabindex: "tabIndex",1446 usemap: "useMap",1447 frameborder: "frameBorder"1448 };1449 1450 jQuery.fn.extend({1451 attr: function( name, value ) {1452 return jQuery.access( this, name, value, true, jQuery.attr );1453 },1454 1455 removeAttr: function( name, fn ) {1456 return this.each(function(){1457 jQuery.attr( this, name, "" );1458 if ( this.nodeType === 1 ) {1459 this.removeAttribute( name );1460 }1461 });1462 },1463 1464 addClass: function( value ) {1465 if ( jQuery.isFunction(value) ) {1466 return this.each(function(i) {1467 var self = jQuery(this);1468 self.addClass( value.call(this, i, self.attr("class")) );1469 });1470 }1471 1472 if ( value && typeof value === "string" ) {1473 var classNames = (value || "").split( rspaces );1474 1475 for ( var i = 0, l = this.length; i < l; i++ ) {1476 var elem = this[i];1477 1478 if ( elem.nodeType === 1 ) {1479 if ( !elem.className ) {1480 elem.className = value;1481 1482 } else {1483 var className = " " + elem.className + " ",1484 setClass = elem.className;1485 1486 for ( var c = 0, cl = classNames.length; c < cl; c++ ) {1487 if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {1488 setClass += " " + classNames[c];1489 }1490 }1491 elem.className = jQuery.trim( setClass );1492 }1493 }1494 }1495 }1496 1497 return this;1498 },1499 1500 removeClass: function( value ) {1501 if ( jQuery.isFunction(value) ) {1502 return this.each(function(i) {1503 var self = jQuery(this);1504 self.removeClass( value.call(this, i, self.attr("class")) );1505 });1506 }1507 1508 if ( (value && typeof value === "string") || value === undefined ) {1509 var classNames = (value || "").split( rspaces );1510 1511 for ( var i = 0, l = this.length; i < l; i++ ) {1512 var elem = this[i];1513 1514 if ( elem.nodeType === 1 && elem.className ) {1515 if ( value ) {1516 var className = (" " + elem.className + " ").replace(rclass, " ");1517 for ( var c = 0, cl = classNames.length; c < cl; c++ ) {1518 className = className.replace(" " + classNames[c] + " ", " ");1519 }1520 elem.className = jQuery.trim( className );1521 1522 } else {1523 elem.className = "";1524 }1525 }1526 }1527 }1528 1529 return this;1530 },1531 1532 toggleClass: function( value, stateVal ) {1533 var type = typeof value,1534 isBool = typeof stateVal === "boolean";1535 1536 if ( jQuery.isFunction( value ) ) {1537 return this.each(function(i) {1538 var self = jQuery(this);1539 self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );1540 });1541 }1542 1543 return this.each(function() {1544 if ( type === "string" ) {1545 // toggle individual class names1546 var className,1547 i = 0,1548 self = jQuery( this ),1549 state = stateVal,1550 classNames = value.split( rspaces );1551 1552 while ( (className = classNames[ i++ ]) ) {1553 // check each className given, space seperated list1554 state = isBool ? state : !self.hasClass( className );1555 self[ state ? "addClass" : "removeClass" ]( className );1556 }1557 1558 } else if ( type === "undefined" || type === "boolean" ) {1559 if ( this.className ) {1560 // store className if set1561 jQuery.data( this, "__className__", this.className );1562 }1563 1564 // toggle whole className1565 this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";1566 }1567 });1568 },1569 1570 hasClass: function( selector ) {1571 var className = " " + selector + " ";1572 for ( var i = 0, l = this.length; i < l; i++ ) {1573 if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {1574 return true;1575 }1576 }1577 1578 return false;1579 },1580 1581 val: function( value ) {1582 if ( !arguments.length ) {1583 var elem = this[0];1584 1585 if ( elem ) {1586 if ( jQuery.nodeName( elem, "option" ) ) {1587 // attributes.value is undefined in Blackberry 4.7 but1588 // uses .value. See #69321589 var val = elem.attributes.value;1590 return !val || val.specified ? elem.value : elem.text;1591 }1592 1593 // We need to handle select boxes special1594 if ( jQuery.nodeName( elem, "select" ) ) {1595 var index = elem.selectedIndex,1596 values = [],1597 options = elem.options,1598 one = elem.type === "select-one";1599 1600 // Nothing was selected1601 if ( index < 0 ) {1602 return null;1603 }1604 1605 // Loop through all the selected options1606 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {1607 var option = options[ i ];1608 1609 // Don't return options that are disabled or in a disabled optgroup1610 if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && 1611 (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {1612 1613 // Get the specific value for the option1614 value = jQuery(option).val();1615 1616 // We don't need an array for one selects1617 if ( one ) {1618 return value;1619 }1620 1621 // Multi-Selects return an array1622 values.push( value );1623 }1624 }1625 1626 return values;1627 }1628 1629 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified1630 if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {1631 return elem.getAttribute("value") === null ? "on" : elem.value;1632 }1633 1634 1635 // Everything else, we just grab the value1636 return (elem.value || "").replace(rreturn, "");1637 1638 }1639 1640 return undefined;1641 }1642 1643 var isFunction = jQuery.isFunction(value);1644 1645 return this.each(function(i) {1646 var self = jQuery(this), val = value;1647 1648 if ( this.nodeType !== 1 ) {1649 return;1650 }1651 1652 if ( isFunction ) {1653 val = value.call(this, i, self.val());1654 }1655 1656 // Treat null/undefined as ""; convert numbers to string1657 if ( val == null ) {1658 val = "";1659 } else if ( typeof val === "number" ) {1660 val += "";1661 } else if ( jQuery.isArray(val) ) {1662 val = jQuery.map(val, function (value) {1663 return value == null ? "" : value + "";1664 });1665 }1666 1667 if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {1668 this.checked = jQuery.inArray( self.val(), val ) >= 0;1669 1670 } else if ( jQuery.nodeName( this, "select" ) ) {1671 var values = jQuery.makeArray(val);1672 1673 jQuery( "option", this ).each(function() {1674 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;1675 });1676 1677 if ( !values.length ) {1678 this.selectedIndex = -1;1679 }1680 1681 } else {1682 this.value = val;1683 }1684 });1685 }1686 });1687 1688 jQuery.extend({1689 attrFn: {1690 val: true,1691 css: true,1692 html: true,1693 text: true,1694 data: true,1695 width: true,1696 height: true,1697 offset: true1698 },1699 1700 attr: function( elem, name, value, pass ) {1701 // don't set attributes on text and comment nodes1702 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {1703 return undefined;1704 }1705 1706 if ( pass && name in jQuery.attrFn ) {1707 return jQuery(elem)[name](value);1708 }1709 1710 var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),1711 // Whether we are setting (or getting)1712 set = value !== undefined;1713 1714 // Try to normalize/fix the name1715 name = notxml && jQuery.props[ name ] || name;1716 1717 // These attributes require special treatment1718 var special = rspecialurl.test( name );1719 1720 // Safari mis-reports the default selected property of an option1721 // Accessing the parent's selectedIndex property fixes it1722 if ( name === "selected" && !jQuery.support.optSelected ) {1723 var parent = elem.parentNode;1724 if ( parent ) {1725 parent.selectedIndex;1726 1727 // Make sure that it also works with optgroups, see #57011728 if ( parent.parentNode ) {1729 parent.parentNode.selectedIndex;1730 }1731 }1732 }1733 1734 // If applicable, access the attribute via the DOM 0 way1735 // 'in' checks fail in Blackberry 4.7 #69311736 if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) {1737 if ( set ) {1738 // We can't allow the type property to be changed (since it causes problems in IE)1739 if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {1740 jQuery.error( "type property can't be changed" );1741 }1742 1743 if ( value === null ) {1744 if ( elem.nodeType === 1 ) {1745 elem.removeAttribute( name );1746 }1747 1748 } else {1749 elem[ name ] = value;1750 }1751 }1752 1753 // browsers index elements by id/name on forms, give priority to attributes.1754 if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {1755 return elem.getAttributeNode( name ).nodeValue;1756 }1757 1758 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set1759 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/1760 if ( name === "tabIndex" ) {1761 var attributeNode = elem.getAttributeNode( "tabIndex" );1762 1763 return attributeNode && attributeNode.specified ?1764 attributeNode.value :1765 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?1766 0 :1767 undefined;1768 }1769 1770 return elem[ name ];1771 }1772 1773 if ( !jQuery.support.style && notxml && name === "style" ) {1774 if ( set ) {1775 elem.style.cssText = "" + value;1776 }1777 1778 return elem.style.cssText;1779 }1780 1781 if ( set ) {1782 // convert the value to a string (all browsers do this but IE) see #10701783 elem.setAttribute( name, "" + value );1784 }1785 1786 // Ensure that missing attributes return undefined1787 // Blackberry 4.7 returns "" from getAttribute #69381788 if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) {1789 return undefined;1790 }1791 1792 var attr = !jQuery.support.hrefNormalized && notxml && special ?1793 // Some attributes require a special call on IE1794 elem.getAttribute( name, 2 ) :1795 elem.getAttribute( name );1796 1797 // Non-existent attributes return null, we normalize to undefined1798 return attr === null ? undefined : attr;1799 }1800 });1801 1802 1803 1804 1805 var rnamespaces = //.(.*)$/,1806 rformElems = /^(?:textarea|input|select)$/i,1807 rperiod = //./g,1808 rspace = / /g,1809 rescape = /[^/w/s.|`]/g,1810 fcleanup = function( nm ) {1811 return nm.replace(rescape, "//$&");1812 },1813 focusCounts = { focusin: 0, focusout: 0 };1814 1815 /*1816 * A number of helper functions used for managing events.1817 * Many of the ideas behind this code originated from1818 * Dean Edwards' addEvent library.1819 */1820 jQuery.event = {1821 1822 // Bind an event to an element1823 // Original by Dean Edwards1824 add: function( elem, types, handler, data ) {1825 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {1826 return;1827 }1828 1829 // For whatever reason, IE has trouble passing the window object1830 // around, causing it to be cloned in the process1831 if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {1832 elem = window;1833 }1834 1835 if ( handler === false ) {1836 handler = returnFalse;1837 } else if ( !handler ) {1838 // Fixes bug #7229. Fix recommended by jdalton1839 return;1840 }1841 1842 var handleObjIn, handleObj;1843 1844 if ( handler.handler ) {1845 handleObjIn = handler;1846 handler = handleObjIn.handler;1847 }1848 1849 // Make sure that the function being executed has a unique ID1850 if ( !handler.guid ) {1851 handler.guid = jQuery.guid++;1852 }1853 1854 // Init the element's event structure1855 var elemData = jQuery.data( elem );1856 1857 // If no elemData is found then we must be trying to bind to one of the1858 // banned noData elements1859 if ( !elemData ) {1860 return;1861 }1862 1863 // Use a key less likely to result in collisions for plain JS objects.1864 // Fixes bug #7150.1865 var eventKey = elem.nodeType ? "events" : "__events__",1866 events = elemData[ eventKey ],1867 eventHandle = elemData.handle;1868 1869 if ( typeof events === "function" ) {1870 // On plain objects events is a fn that holds the the data1871 // which prevents this data from being JSON serialized1872 // the function does not need to be called, it just contains the data1873 eventHandle = events.handle;1874 events = events.events;1875 1876 } else if ( !events ) {1877 if ( !elem.nodeType ) {1878 // On plain objects, create a fn that acts as the holder1879 // of the values to avoid JSON serialization of event data1880 elemData[ eventKey ] = elemData = function(){};1881 }1882 1883 elemData.events = events = {};1884 }1885 1886 if ( !eventHandle ) {1887 elemData.handle = eventHandle = function() {1888 // Handle the second event of a trigger and when1889 // an event is called after a page has unloaded1890 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?1891 jQuery.event.handle.apply( eventHandle.elem, arguments ) :1892 undefined;1893 };1894 }1895 1896 // Add elem as a property of the handle function1897 // This is to prevent a memory leak with non-native events in IE.1898 eventHandle.elem = elem;1899 1900 // Handle multiple events separated by a space1901 // jQuery(...).bind("mouseover mouseout", fn);1902 types = types.split(" ");1903 1904 var type, i = 0, namespaces;1905 1906 while ( (type = types[ i++ ]) ) {1907 handleObj = handleObjIn ?1908 jQuery.extend({}, handleObjIn) :1909 { handler: handler, data: data };1910 1911 // Namespaced event handlers1912 if ( type.indexOf(".") > -1 ) {1913 namespaces = type.split(".");1914 type = namespaces.shift();1915 handleObj.namespace = namespaces.slice(0).sort().join(".");1916 1917 } else {1918 namespaces = [];1919 handleObj.namespace = "";1920 }1921 1922 handleObj.type = type;1923 if ( !handleObj.guid ) {1924 handleObj.guid = handler.guid;1925 }1926 1927 // Get the current list of functions bound to this event1928 var handlers = events[ type ],1929 special = jQuery.event.special[ type ] || {};1930 1931 // Init the event handler queue1932 if ( !handlers ) {1933 handlers = events[ type ] = [];1934 1935 // Check for a special event handler1936 // Only use addEventListener/attachEvent if the special1937 // events handler returns false1938 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {1939 // Bind the global event handler to the element1940 if ( elem.addEventListener ) {1941 elem.addEventListener( type, eventHandle, false );1942 1943 } else if ( elem.attachEvent ) {1944 elem.attachEvent( "on" + type, eventHandle );1945 }1946 }1947 }1948 1949 if ( special.add ) { 1950 special.add.call( elem, handleObj ); 1951 1952 if ( !handleObj.handler.guid ) {1953 handleObj.handler.guid = handler.guid;1954 }1955 }1956 1957 // Add the function to the element's handler list1958 handlers.push( handleObj );1959 1960 // Keep track of which events have been used, for global triggering1961 jQuery.event.global[ type ] = true;1962 }1963 1964 // Nullify elem to prevent memory leaks in IE1965 elem = null;1966 },1967 1968 global: {},1969 1970 // Detach an event or set of events from an element1971 remove: function( elem, types, handler, pos ) {1972 // don't do events on text and comment nodes1973 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {1974 return;1975 }1976 1977 if ( handler === false ) {1978 handler = returnFalse;1979 }1980 1981 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,1982 eventKey = elem.nodeType ? "events" : "__events__",1983 elemData = jQuery.data( elem ),1984 events = elemData && elemData[ eventKey ];1985 1986 if ( !elemData || !events ) {1987 return;1988 }1989 1990 if ( typeof events === "function" ) {1991 elemData = events;1992 events = events.events;1993 }1994 1995 // types is actually an event object here1996 if ( types && types.type ) {1997 handler = types.handler;1998 types = types.type;1999 }2000 2001 // Unbind all events for the element2002 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {2003 types = types || "";2004 2005 for ( type in events ) {2006 jQuery.event.remove( elem, type + types );2007 }2008 2009 return;2010 }2011 2012 // Handle multiple events separated by a space2013 // jQuery(...).unbind("mouseover mouseout", fn);2014 types = types.split(" ");2015 2016 while ( (type = types[ i++ ]) ) {2017 origType = type;2018 handleObj = null;2019 all = type.indexOf(".") < 0;2020 namespaces = [];2021 2022 if ( !all ) {2023 // Namespaced event handlers2024 namespaces = type.split(".");2025 type = namespaces.shift();2026 2027 namespace = new RegExp("(^|//.)" + 2028 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("//.(?:.*//.)?") + "(//.|$)");2029 }2030 2031 eventType = events[ type ];2032 2033 if ( !eventType ) {2034 continue;2035 }2036 2037 if ( !handler ) {2038 for ( j = 0; j < eventType.length; j++ ) {2039 handleObj = eventType[ j ];2040 2041 if ( all || namespace.test( handleObj.namespace ) ) {2042 jQuery.event.remove( elem, origType, handleObj.handler, j );2043 eventType.splice( j--, 1 );2044 }2045 }2046 2047 continue;2048 }2049 2050 special = jQuery.event.special[ type ] || {};2051 2052 for ( j = pos || 0; j < eventType.length; j++ ) {2053 handleObj = eventType[ j ];2054 2055 if ( handler.guid === handleObj.guid ) {2056 // remove the given handler for the given type2057 if ( all || namespace.test( handleObj.namespace ) ) {2058 if ( pos == null ) {2059 eventType.splice( j--, 1 );2060 }2061 2062 if ( special.remove ) {2063 special.remove.call( elem, handleObj );2064 }2065 }2066 2067 if ( pos != null ) {2068 break;2069 }2070 }2071 }2072 2073 // remove generic event handler if no more handlers exist2074 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {2075 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {2076 jQuery.removeEvent( elem, type, elemData.handle );2077 }2078 2079 ret = null;2080 delete events[ type ];2081 }2082 }2083 2084 // Remove the expando if it's no longer used2085 if ( jQuery.isEmptyObject( events ) ) {2086 var handle = elemData.handle;2087 if ( handle ) {2088 handle.elem = null;2089 }2090 2091 delete elemData.events;2092 delete elemData.handle;2093 2094 if ( typeof elemData === "function" ) {2095 jQuery.removeData( elem, eventKey );2096 2097 } else if ( jQuery.isEmptyObject( elemData ) ) {2098 jQuery.removeData( elem );2099 }2100 }2101 },2102 2103 // bubbling is internal2104 trigger: function( event, data, elem /*, bubbling */ ) {2105 // Event object or event type2106 var type = event.type || event,2107 bubbling = arguments[3];2108 2109 if ( !bubbling ) {2110 event = typeof event === "object" ?2111 // jQuery.Event object2112 event[ jQuery.expando ] ? event :2113 // Object literal2114 jQuery.extend( jQuery.Event(type), event ) :2115 // Just the event type (string)2116 jQuery.Event(type);2117 2118 if ( type.indexOf("!") >= 0 ) {2119 event.type = type = type.slice(0, -1);2120 event.exclusive = true;2121 }2122 2123 // Handle a global trigger2124 if ( !elem ) {2125 // Don't bubble custom events when global (to avoid too much overhead)2126 event.stopPropagation();2127 2128 // Only trigger if we've ever bound an event for it2129 if ( jQuery.event.global[ type ] ) {2130 jQuery.each( jQuery.cache, function() {2131 if ( this.events && this.events[type] ) {2132 jQuery.event.trigger( event, data, this.handle.elem );2133 }2134 });2135 }2136 }2137 2138 // Handle triggering a single element2139 2140 // don't do events on text and comment nodes2141 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {2142 return undefined;2143 }2144 2145 // Clean up in case it is reused2146 event.result = undefined;2147 event.target = elem;2148 2149 // Clone the incoming data, if any2150 data = jQuery.makeArray( data );2151 data.unshift( event );2152 }2153 2154 event.currentTarget = elem;2155 2156 // Trigger the event, it is assumed that "handle" is a function2157 var handle = elem.nodeType ?2158 jQuery.data( elem, "handle" ) :2159 (jQuery.data( elem, "__events__" ) || {}).handle;2160 2161 if ( handle ) {2162 handle.apply( elem, data );2163 }2164 2165 var parent = elem.parentNode || elem.ownerDocument;2166 2167 // Trigger an inline bound script2168 try {2169 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {2170 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {2171 event.result = false;2172 event.preventDefault();2173 }2174 }2175 2176 // prevent IE from throwing an error for some elements with some event types, see #35332177 } catch (inlineError) {}2178 2179 if ( !event.isPropagationStopped() && parent ) {2180 jQuery.event.trigger( event, data, parent, true );2181 2182 } else if ( !event.isDefaultPrevented() ) {2183 var old,2184 target = event.target,2185 targetType = type.replace( rnamespaces, "" ),2186 isClick = jQuery.nodeName( target, "a" ) && targetType === "click",2187 special = jQuery.event.special[ targetType ] || {};2188 2189 if ( (!special._default || special._default.call( elem, event ) === false) && 2190 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {2191 2192 try {2193 if ( target[ targetType ] ) {2194 // Make sure that we don't accidentally re-trigger the onFOO events2195 old = target[ "on" + targetType ];2196 2197 if ( old ) {2198 target[ "on" + targetType ] = null;2199 }2200 2201 jQuery.event.triggered = true;2202 target[ targetType ]();2203 }2204 2205 // prevent IE from throwing an error for some elements with some event types, see #35332206 } catch (triggerError) {}2207 2208 if ( old ) {2209 target[ "on" + targetType ] = old;2210 }2211 2212 jQuery.event.triggered = false;2213 }2214 }2215 },2216 2217 handle: function( event ) {2218 var all, handlers, namespaces, namespace_re, events,2219 namespace_sort = [],2220 args = jQuery.makeArray( arguments );2221 2222 event = args[0] = jQuery.event.fix( event || window.event );2223 event.currentTarget = this;2224 2225 // Namespaced event handlers2226 all = event.type.indexOf(".") < 0 && !event.exclusive;2227 2228 if ( !all ) {2229 namespaces = event.type.split(".");2230 event.type = namespaces.shift();2231 namespace_sort = namespaces.slice(0).sort();2232 namespace_re = new RegExp("(^|//.)" + namespace_sort.join("//.(?:.*//.)?") + "(//.|$)");2233 }2234 2235 event.namespace = event.namespace || namespace_sort.join(".");2236 2237 events = jQuery.data(this, this.nodeType ? "events" : "__events__");2238 2239 if ( typeof events === "function" ) {2240 events = events.events;2241 }2242 2243 handlers = (events || {})[ event.type ];2244 2245 if ( events && handlers ) {2246 // Clone the handlers to prevent manipulation2247 handlers = handlers.slice(0);2248 2249 for ( var j = 0, l = handlers.length; j < l; j++ ) {2250 var handleObj = handlers[ j ];2251 2252 // Filter the functions by class2253 if ( all || namespace_re.test( handleObj.namespace ) ) {2254 // Pass in a reference to the handler function itself2255 // So that we can later remove it2256 event.handler = handleObj.handler;2257 event.data = handleObj.data;2258 event.handleObj = handleObj;2259 2260 var ret = handleObj.handler.apply( this, args );2261 2262 if ( ret !== undefined ) {2263 event.result = ret;2264 if ( ret === false ) {2265 event.preventDefault();2266 event.stopPropagation();2267 }2268 }2269 2270 if ( event.isImmediatePropagationStopped() ) {2271 break;2272 }2273 }2274 }2275 }2276 2277 return event.result;2278 },2279 2280 props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),2281 2282 fix: function( event ) {2283 if ( event[ jQuery.expando ] ) {2284 return event;2285 }2286 2287 // store a copy of the original event object2288 // and "clone" to set read-only properties2289 var originalEvent = event;2290 event = jQuery.Event( originalEvent );2291 2292 for ( var i = this.props.length, prop; i; ) {2293 prop = this.props[ --i ];2294 event[ prop ] = originalEvent[ prop ];2295 }2296 2297 // Fix target property, if necessary2298 if ( !event.target ) {2299 // Fixes #1925 where srcElement might not be defined either2300 event.target = event.srcElement || document;2301 }2302 2303 // check if target is a textnode (safari)2304 if ( event.target.nodeType === 3 ) {2305 event.target = event.target.parentNode;2306 }2307 2308 // Add relatedTarget, if necessary2309 if ( !event.relatedTarget && event.fromElement ) {2310 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;2311 }2312 2313 // Calculate pageX/Y if missing and clientX/Y available2314 if ( event.pageX == null && event.clientX != null ) {2315 var doc = document.documentElement,2316 body = document.body;2317 2318 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);2319 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);2320 }2321 2322 // Add which for key events2323 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {2324 event.which = event.charCode != null ? event.charCode : event.keyCode;2325 }2326 2327 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)2328 if ( !event.metaKey && event.ctrlKey ) {2329 event.metaKey = event.ctrlKey;2330 }2331 2332 // Add which for click: 1 === left; 2 === middle; 3 === right2333 // Note: button is not normalized, so don't use it2334 if ( !event.which && event.button !== undefined ) {2335 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));2336 }2337 2338 return event;2339 },2340 2341 // Deprecated, use jQuery.guid instead2342 guid: 1E8,2343 2344 // Deprecated, use jQuery.proxy instead2345 proxy: jQuery.proxy,2346 2347 special: {2348 ready: {2349 // Make sure the ready event is setup2350 setup: jQuery.bindReady,2351 teardown: jQuery.noop2352 },2353 2354 live: {2355 add: function( handleObj ) {2356 jQuery.event.add( this,2357 liveConvert( handleObj.origType, handleObj.selector ),2358 jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); 2359 },2360 2361 remove: function( handleObj ) {2362 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );2363 }2364 },2365 2366 beforeunload: {2367 setup: function( data, namespaces, eventHandle ) {2368 // We only want to do this special case on windows2369 if ( jQuery.isWindow( this ) ) {2370 this.onbeforeunload = eventHandle;2371 }2372 },2373 2374 teardown: function( namespaces, eventHandle ) {2375 if ( this.onbeforeunload === eventHandle ) {2376 this.onbeforeunload = null;2377 }2378 }2379 }2380 }2381 };2382 2383 jQuery.removeEvent = document.removeEventListener ?2384 function( elem, type, handle ) {2385 if ( elem.removeEventListener ) {2386 elem.removeEventListener( type, handle, false );2387 }2388 } : 2389 function( elem, type, handle ) {2390 if ( elem.detachEvent ) {2391 elem.detachEvent( "on" + type, handle );2392 }2393 };2394 2395 jQuery.Event = function( src ) {2396 // Allow instantiation without the 'new' keyword2397 if ( !this.preventDefault ) {2398 return new jQuery.Event( src );2399 }2400 2401 // Event object2402 if ( src && src.type ) {2403 this.originalEvent = src;2404 this.type = src.type;2405 // Event type2406 } else {2407 this.type = src;2408 }2409 2410 // timeStamp is buggy for some events on Firefox(#3843)2411 // So we won't rely on the native value2412 this.timeStamp = jQuery.now();2413 2414 // Mark it as fixed2415 this[ jQuery.expando ] = true;2416 };2417 2418 function returnFalse() {2419 return false;2420 }2421 function returnTrue() {2422 return true;2423 }2424 2425 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding2426 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html2427 jQuery.Event.prototype = {2428 preventDefault: function() {2429 this.isDefaultPrevented = returnTrue;2430 2431 var e = this.originalEvent;2432 if ( !e ) {2433 return;2434 }2435 2436 // if preventDefault exists run it on the original event2437 if ( e.preventDefault ) {2438 e.preventDefault();2439 2440 // otherwise set the returnValue property of the original event to false (IE)2441 } else {2442 e.returnValue = false;2443 }2444 },2445 stopPropagation: function() {2446 this.isPropagationStopped = returnTrue;2447 2448 var e = this.originalEvent;2449 if ( !e ) {2450 return;2451 }2452 // if stopPropagation exists run it on the original event2453 if ( e.stopPropagation ) {2454 e.stopPropagation();2455 }2456 // otherwise set the cancelBubble property of the original event to true (IE)2457 e.cancelBubble = true;2458 },2459 stopImmediatePropagation: function() {2460 this.isImmediatePropagationStopped = returnTrue;2461 this.stopPropagation();2462 },2463 isDefaultPrevented: returnFalse,2464 isPropagationStopped: returnFalse,2465 isImmediatePropagationStopped: returnFalse2466 };2467 2468 // Checks if an event happened on an element within another element2469 // Used in jQuery.event.special.mouseenter and mouseleave handlers2470 var withinElement = function( event ) {2471 // Check if mouse(over|out) are still within the same parent element2472 var parent = event.relatedTarget;2473 2474 // Firefox sometimes assigns relatedTarget a XUL element2475 // which we cannot access the parentNode property of2476 try {2477 // Traverse up the tree2478 while ( parent && parent !== this ) {2479 parent = parent.parentNode;2480 }2481 2482 if ( parent !== this ) {2483 // set the correct event type2484 event.type = event.data;2485 2486 // handle event if we actually just moused on to a non sub-element2487 jQuery.event.handle.apply( this, arguments );2488 }2489 2490 // assuming we've left the element since we most likely mousedover a xul element2491 } catch(e) { }2492 },2493 2494 // In case of event delegation, we only need to rename the event.type,2495 // liveHandler will take care of the rest.2496 delegate = function( event ) {2497 event.type = event.data;2498 jQuery.event.handle.apply( this, arguments );2499 };2500 2501 // Create mouseenter and mouseleave events2502 jQuery.each({2503 mouseenter: "mouseover",2504 mouseleave: "mouseout"2505 }, function( orig, fix ) {2506 jQuery.event.special[ orig ] = {2507 setup: function( data ) {2508 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );2509 },2510 teardown: function( data ) {2511 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );2512 }2513 };2514 });2515 2516 // submit delegation2517 if ( !jQuery.support.submitBubbles ) {2518 2519 jQuery.event.special.submit = {2520 setup: function( data, namespaces ) {2521 if ( this.nodeName.toLowerCase() !== "form" ) {2522 jQuery.event.add(this, "click.specialSubmit", function( e ) {2523 var elem = e.target,2524 type = elem.type;2525 2526 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {2527 e.liveFired = undefined;2528 return trigger( "submit", this, arguments );2529 }2530 });2531 2532 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {2533 var elem = e.target,2534 type = elem.type;2535 2536 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {2537 e.liveFired = undefined;2538 return trigger( "submit", this, arguments );2539 }2540 });2541 2542 } else {2543 return false;2544 }2545 },2546 2547 teardown: function( namespaces ) {2548 jQuery.event.remove( this, ".specialSubmit" );2549 }2550 };2551 2552 }2553 2554 // change delegation, happens here so we have bind.2555 if ( !jQuery.support.changeBubbles ) {2556 2557 var changeFilters,2558 2559 getVal = function( elem ) {2560 var type = elem.type, val = elem.value;2561 2562 if ( type === "radio" || type === "checkbox" ) {2563 val = elem.checked;2564 2565 } else if ( type === "select-multiple" ) {2566 val = elem.selectedIndex > -1 ?2567 jQuery.map( elem.options, function( elem ) {2568 return elem.selected;2569 }).join("-") :2570 "";2571 2572 } else if ( elem.nodeName.toLowerCase() === "select" ) {2573 val = elem.selectedIndex;2574 }2575 2576 return val;2577 },2578 2579 testChange = function testChange( e ) {2580 var elem = e.target, data, val;2581 2582 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {2583 return;2584 }2585 2586 data = jQuery.data( elem, "_change_data" );2587 val = getVal(elem);2588 2589 // the current data will be also retrieved by beforeactivate2590 if ( e.type !== "focusout" || elem.type !== "radio" ) {2591 jQuery.data( elem, "_change_data", val );2592 }2593 2594 if ( data === undefined || val === data ) {2595 return;2596 }2597 2598 if ( data != null || val ) {2599 e.type = "change";2600 e.liveFired = undefined;2601 return jQuery.event.trigger( e, arguments[1], elem );2602 }2603 };2604 2605 jQuery.event.special.change = {2606 filters: {2607 focusout: testChange, 2608 2609 beforedeactivate: testChange,2610 2611 click: function( e ) {2612 var elem = e.target, type = elem.type;2613 2614 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {2615 return testChange.call( this, e );2616 }2617 },2618 2619 // Change has to be called before submit2620 // Keydown will be called before keypress, which is used in submit-event delegation2621 keydown: function( e ) {2622 var elem = e.target, type = elem.type;2623 2624 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||2625 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||2626 type === "select-multiple" ) {2627 return testChange.call( this, e );2628 }2629 },2630 2631 // Beforeactivate happens also before the previous element is blurred2632 // with this event you can't trigger a change event, but you can store2633 // information2634 beforeactivate: function( e ) {2635 var elem = e.target;2636 jQuery.data( elem, "_change_data", getVal(elem) );2637 }2638 },2639 2640 setup: function( data, namespaces ) {2641 if ( this.type === "file" ) {2642 return false;2643 }2644 2645 for ( var type in changeFilters ) {2646 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );2647 }2648 2649 return rformElems.test( this.nodeName );2650 },2651 2652 teardown: function( namespaces ) {2653 jQuery.event.remove( this, ".specialChange" );2654 2655 return rformElems.test( this.nodeName );2656 }2657 };2658 2659 changeFilters = jQuery.event.special.change.filters;2660 2661 // Handle when the input is .focus()'d2662 changeFilters.focus = changeFilters.beforeactivate;2663 }2664 2665 function trigger( type, elem, args ) {2666 args[0].type = type;2667 return jQuery.event.handle.apply( elem, args );2668 }2669 2670 // Create "bubbling" focus and blur events2671 if ( document.addEventListener ) {2672 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {2673 jQuery.event.special[ fix ] = {2674 setup: function() {2675 if ( focusCounts[fix]++ === 0 ) {2676 document.addEventListener( orig, handler, true );2677 }2678 }, 2679 teardown: function() { 2680 if ( --focusCounts[fix] === 0 ) {2681 document.removeEventListener( orig, handler, true );2682 }2683 }2684 };2685 2686 function handler( e ) { 2687 e = jQuery.event.fix( e );2688 e.type = fix;2689 return jQuery.event.trigger( e, null, e.target );2690 }2691 });2692 }2693 2694 jQuery.each(["bind", "one"], function( i, name ) {2695 jQuery.fn[ name ] = function( type, data, fn ) {2696 // Handle object literals2697 if ( typeof type === "object" ) {2698 for ( var key in type ) {2699 this[ name ](key, data, type[key], fn);2700 }2701 return this;2702 }2703 2704 if ( jQuery.isFunction( data ) || data === false ) {2705 fn = data;2706 data = undefined;2707 }2708 2709 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {2710 jQuery( this ).unbind( event, handler );2711 return fn.apply( this, arguments );2712 }) : fn;2713 2714 if ( type === "unload" && name !== "one" ) {2715 this.one( type, data, fn );2716 2717 } else {2718 for ( var i = 0, l = this.length; i < l; i++ ) {2719 jQuery.event.add( this[i], type, handler, data );2720 }2721 }2722 2723 return this;2724 };2725 });2726 2727 jQuery.fn.extend({2728 unbind: function( type, fn ) {2729 // Handle object literals2730 if ( typeof type === "object" && !type.preventDefault ) {2731 for ( var key in type ) {2732 this.unbind(key, type[key]);2733 }2734 2735 } else {2736 for ( var i = 0, l = this.length; i < l; i++ ) {2737 jQuery.event.remove( this[i], type, fn );2738 }2739 }2740 2741 return this;2742 },2743 2744 delegate: function( selector, types, data, fn ) {2745 return this.live( types, data, fn, selector );2746 },2747 2748 undelegate: function( selector, types, fn ) {2749 if ( arguments.length === 0 ) {2750 return this.unbind( "live" );2751 2752 } else {2753 return this.die( types, null, fn, selector );2754 }2755 },2756 2757 trigger: function( type, data ) {2758 return this.each(function() {2759 jQuery.event.trigger( type, data, this );2760 });2761 },2762 2763 triggerHandler: function( type, data ) {2764 if ( this[0] ) {2765 var event = jQuery.Event( type );2766 event.preventDefault();2767 event.stopPropagation();2768 jQuery.event.trigger( event, data, this[0] );2769 return event.result;2770 }2771 },2772 2773 toggle: function( fn ) {2774 // Save reference to arguments for access in closure2775 var args = arguments,2776 i = 1;2777 2778 // link all the functions, so any of them can unbind this click handler2779 while ( i < args.length ) {2780 jQuery.proxy( fn, args[ i++ ] );2781 }2782 2783 return this.click( jQuery.proxy( fn, function( event ) {2784 // Figure out which function to execute2785 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;2786 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );2787 2788 // Make sure that clicks stop2789 event.preventDefault();2790 2791 // and execute the function2792 return args[ lastToggle ].apply( this, arguments ) || false;2793 }));2794 },2795 2796 hover: function( fnOver, fnOut ) {2797 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );2798 }2799 });2800 2801 var liveMap = {2802 focus: "focusin",2803 blur: "focusout",2804 mouseenter: "mouseover",2805 mouseleave: "mouseout"2806 };2807 2808 jQuery.each(["live", "die"], function( i, name ) {2809 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {2810 var type, i = 0, match, namespaces, preType,2811 selector = origSelector || this.selector,2812 context = origSelector ? this : jQuery( this.context );2813 2814 if ( typeof types === "object" && !types.preventDefault ) {2815 for ( var key in types ) {2816 context[ name ]( key, data, types[key], selector );2817 }2818 2819 return this;2820 }2821 2822 if ( jQuery.isFunction( data ) ) {2823 fn = data;2824 data = undefined;2825 }2826 2827 types = (types || "").split(" ");2828 2829 while ( (type = types[ i++ ]) != null ) {2830 match = rnamespaces.exec( type );2831 namespaces = "";2832 2833 if ( match ) {2834 namespaces = match[0];2835 type = type.replace( rnamespaces, "" );2836 }2837 2838 if ( type === "hover" ) {2839 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );2840 continue;2841 }2842 2843 preType = type;2844 2845 if ( type === "focus" || type === "blur" ) {2846 types.push( liveMap[ type ] + namespaces );2847 type = type + namespaces;2848 2849 } else {2850 type = (liveMap[ type ] || type) + namespaces;2851 }2852 2853 if ( name === "live" ) {2854 // bind live handler2855 for ( var j = 0, l = context.length; j < l; j++ ) {2856 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),2857 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );2858 }2859 2860 } else {2861 // unbind live handler2862 context.unbind( "live." + liveConvert( type, selector ), fn );2863 }2864 }2865 2866 return this;2867 };2868 });2869 2870 function liveHandler( event ) {2871 var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,2872 elems = [],2873 selectors = [],2874 events = jQuery.data( this, this.nodeType ? "events" : "__events__" );2875 2876 if ( typeof events === "function" ) {2877 events = events.events;2878 }2879 2880 // Make sure we avoid non-left-click bubbling in Firefox (#3861)2881 if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {2882 return;2883 }2884 2885 if ( event.namespace ) {2886 namespace = new RegExp("(^|//.)" + event.namespace.split(".").join("//.(?:.*//.)?") + "(//.|$)");2887 }2888 2889 event.liveFired = this;2890 2891 var live = events.live.slice(0);2892 2893 for ( j = 0; j < live.length; j++ ) {2894 handleObj = live[j];2895 2896 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {2897 selectors.push( handleObj.selector );2898 2899 } else {2900 live.splice( j--, 1 );2901 }2902 }2903 2904 match = jQuery( event.target ).closest( selectors, event.currentTarget );2905 2906 for ( i = 0, l = match.length; i < l; i++ ) {2907 close = match[i];2908 2909 for ( j = 0; j < live.length; j++ ) {2910 handleObj = live[j];2911 2912 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {2913 elem = close.elem;2914 related = null;2915 2916 // Those two events require additional checking2917 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {2918 event.type = handleObj.preType;2919 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];2920 }2921 2922 if ( !related || related !== elem ) {2923 elems.push({ elem: elem, handleObj: handleObj, level: close.level });2924 }2925 }2926 }2927 }2928 2929 for ( i = 0, l = elems.length; i < l; i++ ) {2930 match = elems[i];2931 2932 if ( maxLevel && match.level > maxLevel ) {2933 break;2934 }2935 2936 event.currentTarget = match.elem;2937 event.data = match.handleObj.data;2938 event.handleObj = match.handleObj;2939 2940 ret = match.handleObj.origHandler.apply( match.elem, arguments );2941 2942 if ( ret === false || event.isPropagationStopped() ) {2943 maxLevel = match.level;2944 2945 if ( ret === false ) {2946 stop = false;2947 }2948 if ( event.isImmediatePropagationStopped() ) {2949 break;2950 }2951 }2952 }2953 2954 return stop;2955 }2956 2957 function liveConvert( type, selector ) {2958 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");2959 }2960 2961 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +2962 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +2963 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {2964 2965 // Handle event binding2966 jQuery.fn[ name ] = function( data, fn ) {2967 if ( fn == null ) {2968 fn = data;2969 data = null;2970 }2971 2972 return arguments.length > 0 ?2973 this.bind( name, data, fn ) :2974 this.trigger( name );2975 };2976 2977 if ( jQuery.attrFn ) {2978 jQuery.attrFn[ name ] = true;2979 }2980 });2981 2982 // Prevent memory leaks in IE2983 // Window isn't included so as not to unbind existing unload events2984 // More info:2985 // - http://isaacschlueter.com/2006/10/msie-memory-leaks/2986 if ( window.attachEvent && !window.addEventListener ) {2987 jQuery(window).bind("unload", function() {2988 for ( var id in jQuery.cache ) {2989 if ( jQuery.cache[ id ].handle ) {2990 // Try/Catch is to handle iframes being unloaded, see #42802991 try {2992 jQuery.event.remove( jQuery.cache[ id ].handle.elem );2993 } catch(e) {}2994 }2995 }2996 });2997 }2998 2999 3000 /*!3001 * Sizzle CSS Selector Engine - v1.03002 * Copyright 2009, The Dojo Foundation3003 * Released under the MIT, BSD, and GPL Licenses.3004 * More information: http://sizzlejs.com/3005 */3006 (function(){3007 3008 var chunker = /((?:/((?:/([^()]+/)|[^()]+)+/)|/[(?:/[[^/[/]]*/]|['"][^'"]*['"]|[^/[/]'"]+)+/]|//.|[^ >+~,(/[//]+)+|[>+~])(/s*,/s*)?((?:.|/r|/n)*)/g,3009 done = 0,3010 toString = Object.prototype.toString,3011 hasDuplicate = false,3012 baseHasDuplicate = true;3013 3014 // Here we check if the JavaScript engine is using some sort of3015 // optimization where it does not always call our comparision3016 // function. If that is the case, discard the hasDuplicate value.3017 // Thus far that includes Google Chrome.3018 [0, 0].sort(function() {3019 baseHasDuplicate = false;3020 return 0;3021 });3022 3023 var Sizzle = function( selector, context, results, seed ) {3024 results = results || [];3025 context = context || document;3026 3027 var origContext = context;3028 3029 if ( context.nodeType !== 1 && context.nodeType !== 9 ) {3030 return [];3031 }3032 3033 if ( !selector || typeof selector !== "string" ) {3034 return results;3035 }3036 3037 var m, set, checkSet, extra, ret, cur, pop, i,3038 prune = true,3039 contextXML = Sizzle.isXML( context ),3040 parts = [],3041 soFar = selector;3042 3043 // Reset the position of the chunker regexp (start from head)3044 do {3045 chunker.exec( "" );3046 m = chunker.exec( soFar );3047 3048 if ( m ) {3049 soFar = m[3];3050 3051 parts.push( m[1] );3052 3053 if ( m[2] ) {3054 extra = m[3];3055 break;3056 }3057 }3058 } while ( m );3059 3060 if ( parts.length > 1 && origPOS.exec( selector ) ) {3061 3062 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {3063 set = posProcess( parts[0] + parts[1], context );3064 3065 } else {3066 set = Expr.relative[ parts[0] ] ?3067 [ context ] :3068 Sizzle( parts.shift(), context );3069 3070 while ( parts.length ) {3071 selector = parts.shift();3072 3073 if ( Expr.relative[ selector ] ) {3074 selector += parts.shift();3075 }3076 3077 set = posProcess( selector, set );3078 }3079 }3080 3081 } else {3082 // Take a shortcut and set the context if the root selector is an ID3083 // (but not if it'll be faster if the inner selector is an ID)3084 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&3085 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {3086 3087 ret = Sizzle.find( parts.shift(), context, contextXML );3088 context = ret.expr ?3089 Sizzle.filter( ret.expr, ret.set )[0] :3090 ret.set[0];3091 }3092 3093 if ( context ) {3094 ret = seed ?3095 { expr: parts.pop(), set: makeArray(seed) } :3096 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );3097 3098 set = ret.expr ?3099 Sizzle.filter( ret.expr, ret.set ) :3100 ret.set;3101 3102 if ( parts.length > 0 ) {3103 checkSet = makeArray( set );3104 3105 } else {3106 prune = false;3107 }3108 3109 while ( parts.length ) {3110 cur = parts.pop();3111 pop = cur;3112 3113 if ( !Expr.relative[ cur ] ) {3114 cur = "";3115 } else {3116 pop = parts.pop();3117 }3118 3119 if ( pop == null ) {3120 pop = context;3121 }3122 3123 Expr.relative[ cur ]( checkSet, pop, contextXML );3124 }3125 3126 } else {3127 checkSet = parts = [];3128 }3129 }3130 3131 if ( !checkSet ) {3132 checkSet = set;3133 }3134 3135 if ( !checkSet ) {3136 Sizzle.error( cur || selector );3137 }3138 3139 if ( toString.call(checkSet) === "[object Array]" ) {3140 if ( !prune ) {3141 results.push.apply( results, checkSet );3142 3143 } else if ( context && context.nodeType === 1 ) {3144 for ( i = 0; checkSet[i] != null; i++ ) {3145 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {3146 results.push( set[i] );3147 }3148 }3149 3150 } else {3151 for ( i = 0; checkSet[i] != null; i++ ) {3152 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {3153 results.push( set[i] );3154 }3155 }3156 }3157 3158 } else {3159 makeArray( checkSet, results );3160 }3161 3162 if ( extra ) {3163 Sizzle( extra, origContext, results, seed );3164 Sizzle.uniqueSort( results );3165 }3166 3167 return results;3168 };3169 3170 Sizzle.uniqueSort = function( results ) {3171 if ( sortOrder ) {3172 hasDuplicate = baseHasDuplicate;3173 results.sort( sortOrder );3174 3175 if ( hasDuplicate ) {3176 for ( var i = 1; i < results.length; i++ ) {3177 if ( results[i] === results[ i - 1 ] ) {3178 results.splice( i--, 1 );3179 }3180 }3181 }3182 }3183 3184 return results;3185 };3186 3187 Sizzle.matches = function( expr, set ) {3188 return Sizzle( expr, null, null, set );3189 };3190 3191 Sizzle.matchesSelector = function( node, expr ) {3192 return Sizzle( expr, null, null, [node] ).length > 0;3193 };3194 3195 Sizzle.find = function( expr, context, isXML ) {3196 var set;3197 3198 if ( !expr ) {3199 return [];3200 }3201 3202 for ( var i = 0, l = Expr.order.length; i < l; i++ ) {3203 var match,3204 type = Expr.order[i];3205 3206 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {3207 var left = match[1];3208 match.splice( 1, 1 );3209 3210 if ( left.substr( left.length - 1 ) !== "//" ) {3211 match[1] = (match[1] || "").replace(////g, "");3212 set = Expr.find[ type ]( match, context, isXML );3213 3214 if ( set != null ) {3215 expr = expr.replace( Expr.match[ type ], "" );3216 break;3217 }3218 }3219 }3220 }3221 3222 if ( !set ) {3223 set = context.getElementsByTagName( "*" );3224 }3225 3226 return { set: set, expr: expr };3227 };3228 3229 Sizzle.filter = function( expr, set, inplace, not ) {3230 var match, anyFound,3231 old = expr,3232 result = [],3233 curLoop = set,3234 isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );3235 3236 while ( expr && set.length ) {3237 for ( var type in Expr.filter ) {3238 if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {3239 var found, item,3240 filter = Expr.filter[ type ],3241 left = match[1];3242 3243 anyFound = false;3244 3245 match.splice(1,1);3246 3247 if ( left.substr( left.length - 1 ) === "//" ) {3248 continue;3249 }3250 3251 if ( curLoop === result ) {3252 result = [];3253 }3254 3255 if ( Expr.preFilter[ type ] ) {3256 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );3257 3258 if ( !match ) {3259 anyFound = found = true;3260 3261 } else if ( match === true ) {3262 continue;3263 }3264 }3265 3266 if ( match ) {3267 for ( var i = 0; (item = curLoop[i]) != null; i++ ) {3268 if ( item ) {3269 found = filter( item, match, i, curLoop );3270 var pass = not ^ !!found;3271 3272 if ( inplace && found != null ) {3273 if ( pass ) {3274 anyFound = true;3275 3276 } else {3277 curLoop[i] = false;3278 }3279 3280 } else if ( pass ) {3281 result.push( item );3282 anyFound = true;3283 }3284 }3285 }3286 }3287 3288 if ( found !== undefined ) {3289 if ( !inplace ) {3290 curLoop = result;3291 }3292 3293 expr = expr.replace( Expr.match[ type ], "" );3294 3295 if ( !anyFound ) {3296 return [];3297 }3298 3299 break;3300 }3301 }3302 }3303 3304 // Improper expression3305 if ( expr === old ) {3306 if ( anyFound == null ) {3307 Sizzle.error( expr );3308 3309 } else {3310 break;3311 }3312 }3313 3314 old = expr;3315 }3316 3317 return curLoop;3318 };3319 3320 Sizzle.error = function( msg ) {3321 throw "Syntax error, unrecognized expression: " + msg;3322 };3323 3324 var Expr = Sizzle.selectors = {3325 order: [ "ID", "NAME", "TAG" ],3326 3327 match: {3328 ID: /#((?:[/w/u00c0-/uFFFF/-]|//.)+)/,3329 CLASS: //.((?:[/w/u00c0-/uFFFF/-]|//.)+)/,3330 NAME: //[name=['"]*((?:[/w/u00c0-/uFFFF/-]|//.)+)['"]*/]/,3331 ATTR: //[/s*((?:[/w/u00c0-/uFFFF/-]|//.)+)/s*(?:(/S?=)/s*(['"]*)(.*?)/3|)/s*/]/,3332 TAG: /^((?:[/w/u00c0-/uFFFF/*/-]|//.)+)/,3333 CHILD: /:(only|nth|last|first)-child(?:/((even|odd|[/dn+/-]*)/))?/,3334 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:/((/d*)/))?(?=[^/-]|$)/,3335 PSEUDO: /:((?:[/w/u00c0-/uFFFF/-]|//.)+)(?:/((['"]?)((?:/([^/)]+/)|[^/(/)]*)+)/2/))?/3336 },3337 3338 leftMatch: {},3339 3340 attrMap: {3341 "class": "className",3342 "for": "htmlFor"3343 },3344 3345 attrHandle: {3346 href: function( elem ) {3347 return elem.getAttribute( "href" );3348 }3349 },3350 3351 relative: {3352 "+": function(checkSet, part){3353 var isPartStr = typeof part === "string",3354 isTag = isPartStr && !//W/.test( part ),3355 isPartStrNotTag = isPartStr && !isTag;3356 3357 if ( isTag ) {3358 part = part.toLowerCase();3359 }3360 3361 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {3362 if ( (elem = checkSet[i]) ) {3363 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}3364 3365 checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?3366 elem || false :3367 elem === part;3368 }3369 }3370 3371 if ( isPartStrNotTag ) {3372 Sizzle.filter( part, checkSet, true );3373 }3374 },3375 3376 ">": function( checkSet, part ) {3377 var elem,3378 isPartStr = typeof part === "string",3379 i = 0,3380 l = checkSet.length;3381 3382 if ( isPartStr && !//W/.test( part ) ) {3383 part = part.toLowerCase();3384 3385 for ( ; i < l; i++ ) {3386 elem = checkSet[i];3387 3388 if ( elem ) {3389 var parent = elem.parentNode;3390 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;3391 }3392 }3393 3394 } else {3395 for ( ; i < l; i++ ) {3396 elem = checkSet[i];3397 3398 if ( elem ) {3399 checkSet[i] = isPartStr ?3400 elem.parentNode :3401 elem.parentNode === part;3402 }3403 }3404 3405 if ( isPartStr ) {3406 Sizzle.filter( part, checkSet, true );3407 }3408 }3409 },3410 3411 "": function(checkSet, part, isXML){3412 var nodeCheck,3413 doneName = done++,3414 checkFn = dirCheck;3415 3416 if ( typeof part === "string" && !//W/.test(part) ) {3417 part = part.toLowerCase();3418 nodeCheck = part;3419 checkFn = dirNodeCheck;3420 }3421 3422 checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );3423 },3424 3425 "~": function( checkSet, part, isXML ) {3426 var nodeCheck,3427 doneName = done++,3428 checkFn = dirCheck;3429 3430 if ( typeof part === "string" && !//W/.test( part ) ) {3431 part = part.toLowerCase();3432 nodeCheck = part;3433 checkFn = dirNodeCheck;3434 }3435 3436 checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );3437 }3438 },3439 3440 find: {3441 ID: function( match, context, isXML ) {3442 if ( typeof context.getElementById !== "undefined" && !isXML ) {3443 var m = context.getElementById(match[1]);3444 // Check parentNode to catch when Blackberry 4.6 returns3445 // nodes that are no longer in the document #69633446 return m && m.parentNode ? [m] : [];3447 }3448 },3449 3450 NAME: function( match, context ) {3451 if ( typeof context.getElementsByName !== "undefined" ) {3452 var ret = [],3453 results = context.getElementsByName( match[1] );3454 3455 for ( var i = 0, l = results.length; i < l; i++ ) {3456 if ( results[i].getAttribute("name") === match[1] ) {3457 ret.push( results[i] );3458 }3459 }3460 3461 return ret.length === 0 ? null : ret;3462 }3463 },3464 3465 TAG: function( match, context ) {3466 return context.getElementsByTagName( match[1] );3467 }3468 },3469 preFilter: {3470 CLASS: function( match, curLoop, inplace, result, not, isXML ) {3471 match = " " + match[1].replace(////g, "") + " ";3472 3473 if ( isXML ) {3474 return match;3475 }3476 3477 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {3478 if ( elem ) {3479 if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[/t/n]/g, " ").indexOf(match) >= 0) ) {3480 if ( !inplace ) {3481 result.push( elem );3482 }3483 3484 } else if ( inplace ) {3485 curLoop[i] = false;3486 }3487 }3488 }3489 3490 return false;3491 },3492 3493 ID: function( match ) {3494 return match[1].replace(////g, "");3495 },3496 3497 TAG: function( match, curLoop ) {3498 return match[1].toLowerCase();3499 },3500 3501 CHILD: function( match ) {3502 if ( match[1] === "nth" ) {3503 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'3504 var test = /(-?)(/d*)n((?:/+|-)?/d*)/.exec(3505 match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||3506 !//D/.test( match[2] ) && "0n+" + match[2] || match[2]);3507 3508 // calculate the numbers (first)n+(last) including if they are negative3509 match[2] = (test[1] + (test[2] || 1)) - 0;3510 match[3] = test[3] - 0;3511 }3512 3513 // TODO: Move to normal caching system3514 match[0] = done++;3515 3516 return match;3517 },3518 3519 ATTR: function( match, curLoop, inplace, result, not, isXML ) {3520 var name = match[1].replace(////g, "");3521 3522 if ( !isXML && Expr.attrMap[name] ) {3523 match[1] = Expr.attrMap[name];3524 }3525 3526 if ( match[2] === "~=" ) {3527 match[4] = " " + match[4] + " ";3528 }3529 3530 return match;3531 },3532 3533 PSEUDO: function( match, curLoop, inplace, result, not ) {3534 if ( match[1] === "not" ) {3535 // If we're dealing with a complex expression, or a simple one3536 if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^/w/.test(match[3]) ) {3537 match[3] = Sizzle(match[3], null, null, curLoop);3538 3539 } else {3540 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);3541 3542 if ( !inplace ) {3543 result.push.apply( result, ret );3544 }3545 3546 return false;3547 }3548 3549 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {3550 return true;3551 }3552 3553 return match;3554 },3555 3556 POS: function( match ) {3557 match.unshift( true );3558 3559 return match;3560 }3561 },3562 3563 filters: {3564 enabled: function( elem ) {3565 return elem.disabled === false && elem.type !== "hidden";3566 },3567 3568 disabled: function( elem ) {3569 return elem.disabled === true;3570 },3571 3572 checked: function( elem ) {3573 return elem.checked === true;3574 },3575 3576 selected: function( elem ) {3577 // Accessing this property makes selected-by-default3578 // options in Safari work properly3579 elem.parentNode.selectedIndex;3580 3581 return elem.selected === true;3582 },3583 3584 parent: function( elem ) {3585 return !!elem.firstChild;3586 },3587 3588 empty: function( elem ) {3589 return !elem.firstChild;3590 },3591 3592 has: function( elem, i, match ) {3593 return !!Sizzle( match[3], elem ).length;3594 },3595 3596 header: function( elem ) {3597 return (/h/d/i).test( elem.nodeName );3598 },3599 3600 text: function( elem ) {3601 return "text" === elem.type;3602 },3603 radio: function( elem ) {3604 return "radio" === elem.type;3605 },3606 3607 checkbox: function( elem ) {3608 return "checkbox" === elem.type;3609 },3610 3611 file: function( elem ) {3612 return "file" === elem.type;3613 },3614 password: function( elem ) {3615 return "password" === elem.type;3616 },3617 3618 submit: function( elem ) {3619 return "submit" === elem.type;3620 },3621 3622 image: function( elem ) {3623 return "image" === elem.type;3624 },3625 3626 reset: function( elem ) {3627 return "reset" === elem.type;3628 },3629 3630 button: function( elem ) {3631 return "button" === elem.type || elem.nodeName.toLowerCase() === "button";3632 },3633 3634 input: function( elem ) {3635 return (/input|select|textarea|button/i).test( elem.nodeName );3636 }3637 },3638 setFilters: {3639 first: function( elem, i ) {3640 return i === 0;3641 },3642 3643 last: function( elem, i, match, array ) {3644 return i === array.length - 1;3645 },3646 3647 even: function( elem, i ) {3648 return i % 2 === 0;3649 },3650 3651 odd: function( elem, i ) {3652 return i % 2 === 1;3653 },3654 3655 lt: function( elem, i, match ) {3656 return i < match[3] - 0;3657 },3658 3659 gt: function( elem, i, match ) {3660 return i > match[3] - 0;3661 },3662 3663 nth: function( elem, i, match ) {3664 return match[3] - 0 === i;3665 },3666 3667 eq: function( elem, i, match ) {3668 return match[3] - 0 === i;3669 }3670 },3671 filter: {3672 PSEUDO: function( elem, match, i, array ) {3673 var name = match[1],3674 filter = Expr.filters[ name ];3675 3676 if ( filter ) {3677 return filter( elem, i, match, array );3678 3679 } else if ( name === "contains" ) {3680 return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;3681 3682 } else if ( name === "not" ) {3683 var not = match[3];3684 3685 for ( var j = 0, l = not.length; j < l; j++ ) {3686 if ( not[j] === elem ) {3687 return false;3688 }3689 }3690 3691 return true;3692 3693 } else {3694 Sizzle.error( "Syntax error, unrecognized expression: " + name );3695 }3696 },3697 3698 CHILD: function( elem, match ) {3699 var type = match[1],3700 node = elem;3701 3702 switch ( type ) {3703 case "only":3704 case "first":3705 while ( (node = node.previousSibling) ) {3706 if ( node.nodeType === 1 ) { 3707 return false; 3708 }3709 }3710 3711 if ( type === "first" ) { 3712 return true; 3713 }3714 3715 node = elem;3716 3717 case "last":3718 while ( (node = node.nextSibling) ) {3719 if ( node.nodeType === 1 ) { 3720 return false; 3721 }3722 }3723 3724 return true;3725 3726 case "nth":3727 var first = match[2],3728 last = match[3];3729 3730 if ( first === 1 && last === 0 ) {3731 return true;3732 }3733 3734 var doneName = match[0],3735 parent = elem.parentNode;3736 3737 if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {3738 var count = 0;3739 3740 for ( node = parent.firstChild; node; node = node.nextSibling ) {3741 if ( node.nodeType === 1 ) {3742 node.nodeIndex = ++count;3743 }3744 } 3745 3746 parent.sizcache = doneName;3747 }3748 3749 var diff = elem.nodeIndex - last;3750 3751 if ( first === 0 ) {3752 return diff === 0;3753 3754 } else {3755 return ( diff % first === 0 && diff / first >= 0 );3756 }3757 }3758 },3759 3760 ID: function( elem, match ) {3761 return elem.nodeType === 1 && elem.getAttribute("id") === match;3762 },3763 3764 TAG: function( elem, match ) {3765 return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;3766 },3767 3768 CLASS: function( elem, match ) {3769 return (" " + (elem.className || elem.getAttribute("class")) + " ")3770 .indexOf( match ) > -1;3771 },3772 3773 ATTR: function( elem, match ) {3774 var name = match[1],3775 result = Expr.attrHandle[ name ] ?3776 Expr.attrHandle[ name ]( elem ) :3777 elem[ name ] != null ?3778 elem[ name ] :3779 elem.getAttribute( name ),3780 value = result + "",3781 type = match[2],3782 check = match[4];3783 3784 return result == null ?3785 type === "!=" :3786 type === "=" ?3787 value === check :3788 type === "*=" ?3789 value.indexOf(check) >= 0 :3790 type === "~=" ?3791 (" " + value + " ").indexOf(check) >= 0 :3792 !check ?3793 value && result !== false :3794 type === "!=" ?3795 value !== check :3796 type === "^=" ?3797 value.indexOf(check) === 0 :3798 type === "$=" ?3799 value.substr(value.length - check.length) === check :3800 type === "|=" ?3801 value === check || value.substr(0, check.length + 1) === check + "-" :3802 false;3803 },3804 3805 POS: function( elem, match, i, array ) {3806 var name = match[2],3807 filter = Expr.setFilters[ name ];3808 3809 if ( filter ) {3810 return filter( elem, i, match, array );3811 }3812 }3813 }3814 };3815 3816 var origPOS = Expr.match.POS,3817 fescape = function(all, num){3818 return "//" + (num - 0 + 1);3819 };3820 3821 for ( var type in Expr.match ) {3822 Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^/[]*/])(?![^/(]*/))/.source) );3823 Expr.leftMatch[ type ] = new RegExp( /(^(?:.|/r|/n)*?)/.source + Expr.match[ type ].source.replace(///(/d+)/g, fescape) );3824 }3825 3826 var makeArray = function( array, results ) {3827 array = Array.prototype.slice.call( array, 0 );3828 3829 if ( results ) {3830 results.push.apply( results, array );3831 return results;3832 }3833 3834 return array;3835 };3836 3837 // Perform a simple check to determine if the browser is capable of3838 // converting a NodeList to an array using builtin methods.3839 // Also verifies that the returned array holds DOM nodes3840 // (which is not the case in the Blackberry browser)3841 try {3842 Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;3843 3844 // Provide a fallback method if it does not work3845 } catch( e ) {3846 makeArray = function( array, results ) {3847 var i = 0,3848 ret = results || [];3849 3850 if ( toString.call(array) === "[object Array]" ) {3851 Array.prototype.push.apply( ret, array );3852 3853 } else {3854 if ( typeof array.length === "number" ) {3855 for ( var l = array.length; i < l; i++ ) {3856 ret.push( array[i] );3857 }3858 3859 } else {3860 for ( ; array[i]; i++ ) {3861 ret.push( array[i] );3862 }3863 }3864 }3865 3866 return ret;3867 };3868 }3869 3870 var sortOrder, siblingCheck;3871 3872 if ( document.documentElement.compareDocumentPosition ) {3873 sortOrder = function( a, b ) {3874 if ( a === b ) {3875 hasDuplicate = true;3876 return 0;3877 }3878 3879 if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {3880 return a.compareDocumentPosition ? -1 : 1;3881 }3882 3883 return a.compareDocumentPosition(b) & 4 ? -1 : 1;3884 };3885 3886 } else {3887 sortOrder = function( a, b ) {3888 var al, bl,3889 ap = [],3890 bp = [],3891 aup = a.parentNode,3892 bup = b.parentNode,3893 cur = aup;3894 3895 // The nodes are identical, we can exit early3896 if ( a === b ) {3897 hasDuplicate = true;3898 return 0;3899 3900 // If the nodes are siblings (or identical) we can do a quick check3901 } else if ( aup === bup ) {3902 return siblingCheck( a, b );3903 3904 // If no parents were found then the nodes are disconnected3905 } else if ( !aup ) {3906 return -1;3907 3908 } else if ( !bup ) {3909 return 1;3910 }3911 3912 // Otherwise they're somewhere else in the tree so we need3913 // to build up a full list of the parentNodes for comparison3914 while ( cur ) {3915 ap.unshift( cur );3916 cur = cur.parentNode;3917 }3918 3919 cur = bup;3920 3921 while ( cur ) {3922 bp.unshift( cur );3923 cur = cur.parentNode;3924 }3925 3926 al = ap.length;3927 bl = bp.length;3928 3929 // Start walking down the tree looking for a discrepancy3930 for ( var i = 0; i < al && i < bl; i++ ) {3931 if ( ap[i] !== bp[i] ) {3932 return siblingCheck( ap[i], bp[i] );3933 }3934 }3935 3936 // We ended someplace up the tree so do a sibling check3937 return i === al ?3938 siblingCheck( a, bp[i], -1 ) :3939 siblingCheck( ap[i], b, 1 );3940 };3941 3942 siblingCheck = function( a, b, ret ) {3943 if ( a === b ) {3944 return ret;3945 }3946 3947 var cur = a.nextSibling;3948 3949 while ( cur ) {3950 if ( cur === b ) {3951 return -1;3952 }3953 3954 cur = cur.nextSibling;3955 }3956 3957 return 1;3958 };3959 }3960 3961 // Utility function for retreiving the text value of an array of DOM nodes3962 Sizzle.getText = function( elems ) {3963 var ret = "", elem;3964 3965 for ( var i = 0; elems[i]; i++ ) {3966 elem = elems[i];3967 3968 // Get the text from text nodes and CDATA nodes3969 if ( elem.nodeType === 3 || elem.nodeType === 4 ) {3970 ret += elem.nodeValue;3971 3972 // Traverse everything else, except comment nodes3973 } else if ( elem.nodeType !== 8 ) {3974 ret += Sizzle.getText( elem.childNodes );3975 }3976 }3977 3978 return ret;3979 };3980 3981 // Check to see if the browser returns elements by name when3982 // querying by getElementById (and provide a workaround)3983 (function(){3984 // We're going to inject a fake input element with a specified name3985 var form = document.createElement("div"),3986 id = "script" + (new Date()).getTime(),3987 root = document.documentElement;3988 3989 form.innerHTML = "";3990 3991 // Inject it into the root element, check its status, and remove it quickly3992 root.insertBefore( form, root.firstChild );3993 3994 // The workaround has to do additional checks after a getElementById3995 // Which slows things down for other browsers (hence the branching)3996 if ( document.getElementById( id ) ) {3997 Expr.find.ID = function( match, context, isXML ) {3998 if ( typeof context.getElementById !== "undefined" && !isXML ) {3999 var m = context.getElementById(match[1]);4000 4001 return m ?4002 m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?4003 [m] :4004 undefined :4005 [];4006 }4007 };4008 4009 Expr.filter.ID = function( elem, match ) {4010 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");4011 4012 return elem.nodeType === 1 && node && node.nodeValue === match;4013 };4014 }4015 4016 root.removeChild( form );4017 4018 // release memory in IE4019 root = form = null;4020 })();4021 4022 (function(){4023 // Check to see if the browser returns only elements4024 // when doing getElementsByTagName("*")4025 4026 // Create a fake element4027 var div = document.createElement("div");4028 div.appendChild( document.createComment("") );4029 4030 // Make sure no comments are found4031 if ( div.getElementsByTagName("*").length > 0 ) {4032 Expr.find.TAG = function( match, context ) {4033 var results = context.getElementsByTagName( match[1] );4034 4035 // Filter out possible comments4036 if ( match[1] === "*" ) {4037 var tmp = [];4038 4039 for ( var i = 0; results[i]; i++ ) {4040 if ( results[i].nodeType === 1 ) {4041 tmp.push( results[i] );4042 }4043 }4044 4045 results = tmp;4046 }4047 4048 return results;4049 };4050 }4051 4052 // Check to see if an attribute returns normalized href attributes4053 div.innerHTML = "";4054 4055 if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&4056 div.firstChild.getAttribute("href") !== "#" ) {4057 4058 Expr.attrHandle.href = function( elem ) {4059 return elem.getAttribute( "href", 2 );4060 };4061 }4062 4063 // release memory in IE4064 div = null;4065 })();4066 4067 if ( document.querySelectorAll ) {4068 (function(){4069 var oldSizzle = Sizzle,4070 div = document.createElement("div"),4071 id = "__sizzle__";4072 4073 div.innerHTML = "

";4074 4075 // Safari can't handle uppercase or unicode characters when4076 // in quirks mode.4077 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {4078 return;4079 }4080 4081 Sizzle = function( query, context, extra, seed ) {4082 context = context || document;4083 4084 // Make sure that attribute selectors are quoted4085 query = query.replace(//=/s*([^'"/]]*)/s*/]/g, "='$1']");4086 4087 // Only use querySelectorAll on non-XML documents4088 // (ID selectors don't work in non-HTML documents)4089 if ( !seed && !Sizzle.isXML(context) ) {4090 if ( context.nodeType === 9 ) {4091 try {4092 return makeArray( context.querySelectorAll(query), extra );4093 } catch(qsaError) {}4094 4095 // qSA works strangely on Element-rooted queries4096 // We can work around this by specifying an extra ID on the root4097 // and working up from there (Thanks to Andrew Dupont for the technique)4098 // IE 8 doesn't work on object elements4099 } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {4100 var old = context.getAttribute( "id" ),4101 nid = old || id;4102 4103 if ( !old ) {4104 context.setAttribute( "id", nid );4105 }4106 4107 try {4108 return makeArray( context.querySelectorAll( "#" + nid + " " + query ), extra );4109 4110 } catch(pseudoError) {4111 } finally {4112 if ( !old ) {4113 context.removeAttribute( "id" );4114 }4115 }4116 }4117 }4118 4119 return oldSizzle(query, context, extra, seed);4120 };4121 4122 for ( var prop in oldSizzle ) {4123 Sizzle[ prop ] = oldSizzle[ prop ];4124 }4125 4126 // release memory in IE4127 div = null;4128 })();4129 }4130 4131 (function(){4132 var html = document.documentElement,4133 matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector,4134 pseudoWorks = false;4135 4136 try {4137 // This should fail with an exception4138 // Gecko does not error, returns false instead4139 matches.call( document.documentElement, "[test!='']:sizzle" );4140 4141 } catch( pseudoError ) {4142 pseudoWorks = true;4143 }4144 4145 if ( matches ) {4146 Sizzle.matchesSelector = function( node, expr ) {4147 // Make sure that attribute selectors are quoted4148 expr = expr.replace(//=/s*([^'"/]]*)/s*/]/g, "='$1']");4149 4150 if ( !Sizzle.isXML( node ) ) {4151 try { 4152 if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {4153 return matches.call( node, expr );4154 }4155 } catch(e) {}4156 }4157 4158 return Sizzle(expr, null, null, [node]).length > 0;4159 };4160 }4161 })();4162 4163 (function(){4164 var div = document.createElement("div");4165 4166 div.innerHTML = "
";4167 4168 // Opera can't find a second classname (in 9.6)4169 // Also, make sure that getElementsByClassName actually exists4170 if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {4171 return;4172 }4173 4174 // Safari caches class attributes, doesn't catch changes (in 3.2)4175 div.lastChild.className = "e";4176 4177 if ( div.getElementsByClassName("e").length === 1 ) {4178 return;4179 }4180 4181 Expr.order.splice(1, 0, "CLASS");4182 Expr.find.CLASS = function( match, context, isXML ) {4183 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {4184 return context.getElementsByClassName(match[1]);4185 }4186 };4187 4188 // release memory in IE4189 div = null;4190 })();4191 4192 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {4193 for ( var i = 0, l = checkSet.length; i < l; i++ ) {4194 var elem = checkSet[i];4195 4196 if ( elem ) {4197 var match = false;4198 4199 elem = elem[dir];4200 4201 while ( elem ) {4202 if ( elem.sizcache === doneName ) {4203 match = checkSet[elem.sizset];4204 break;4205 }4206 4207 if ( elem.nodeType === 1 && !isXML ){4208 elem.sizcache = doneName;4209 elem.sizset = i;4210 }4211 4212 if ( elem.nodeName.toLowerCase() === cur ) {4213 match = elem;4214 break;4215 }4216 4217 elem = elem[dir];4218 }4219 4220 checkSet[i] = match;4221 }4222 }4223 }4224 4225 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {4226 for ( var i = 0, l = checkSet.length; i < l; i++ ) {4227 var elem = checkSet[i];4228 4229 if ( elem ) {4230 var match = false;4231 4232 elem = elem[dir];4233 4234 while ( elem ) {4235 if ( elem.sizcache === doneName ) {4236 match = checkSet[elem.sizset];4237 break;4238 }4239 4240 if ( elem.nodeType === 1 ) {4241 if ( !isXML ) {4242 elem.sizcache = doneName;4243 elem.sizset = i;4244 }4245 4246 if ( typeof cur !== "string" ) {4247 if ( elem === cur ) {4248 match = true;4249 break;4250 }4251 4252 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {4253 match = elem;4254 break;4255 }4256 }4257 4258 elem = elem[dir];4259 }4260 4261 checkSet[i] = match;4262 }4263 }4264 }4265 4266 if ( document.documentElement.contains ) {4267 Sizzle.contains = function( a, b ) {4268 return a !== b && (a.contains ? a.contains(b) : true);4269 };4270 4271 } else if ( document.documentElement.compareDocumentPosition ) {4272 Sizzle.contains = function( a, b ) {4273 return !!(a.compareDocumentPosition(b) & 16);4274 };4275 4276 } else {4277 Sizzle.contains = function() {4278 return false;4279 };4280 }4281 4282 Sizzle.isXML = function( elem ) {4283 // documentElement is verified for cases where it doesn't yet exist4284 // (such as loading iframes in IE - #4833) 4285 var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;4286 4287 return documentElement ? documentElement.nodeName !== "HTML" : false;4288 };4289 4290 var posProcess = function( selector, context ) {4291 var match,4292 tmpSet = [],4293 later = "",4294 root = context.nodeType ? [context] : context;4295 4296 // Position selectors must be done after the filter4297 // And so must :not(positional) so we move all PSEUDOs to the end4298 while ( (match = Expr.match.PSEUDO.exec( selector )) ) {4299 later += match[0];4300 selector = selector.replace( Expr.match.PSEUDO, "" );4301 }4302 4303 selector = Expr.relative[selector] ? selector + "*" : selector;4304 4305 for ( var i = 0, l = root.length; i < l; i++ ) {4306 Sizzle( selector, root[i], tmpSet );4307 }4308 4309 return Sizzle.filter( later, tmpSet );4310 };4311 4312 // EXPOSE4313 jQuery.find = Sizzle;4314 jQuery.expr = Sizzle.selectors;4315 jQuery.expr[":"] = jQuery.expr.filters;4316 jQuery.unique = Sizzle.uniqueSort;4317 jQuery.text = Sizzle.getText;4318 jQuery.isXMLDoc = Sizzle.isXML;4319 jQuery.contains = Sizzle.contains;4320 4321 4322 })();4323 4324 4325 var runtil = /Until$/,4326 rparentsprev = /^(?:parents|prevUntil|prevAll)/,4327 // Note: This RegExp should be improved, or likely pulled from Sizzle4328 rmultiselector = /,/,4329 isSimple = /^.[^:#/[/.,]*$/,4330 slice = Array.prototype.slice,4331 POS = jQuery.expr.match.POS;4332 4333 jQuery.fn.extend({4334 find: function( selector ) {4335 var ret = this.pushStack( "", "find", selector ),4336 length = 0;4337 4338 for ( var i = 0, l = this.length; i < l; i++ ) {4339 length = ret.length;4340 jQuery.find( selector, this[i], ret );4341 4342 if ( i > 0 ) {4343 // Make sure that the results are unique4344 for ( var n = length; n < ret.length; n++ ) {4345 for ( var r = 0; r < length; r++ ) {4346 if ( ret[r] === ret[n] ) {4347 ret.splice(n--, 1);4348 break;4349 }4350 }4351 }4352 }4353 }4354 4355 return ret;4356 },4357 4358 has: function( target ) {4359 var targets = jQuery( target );4360 return this.filter(function() {4361 for ( var i = 0, l = targets.length; i < l; i++ ) {4362 if ( jQuery.contains( this, targets[i] ) ) {4363 return true;4364 }4365 }4366 });4367 },4368 4369 not: function( selector ) {4370 return this.pushStack( winnow(this, selector, false), "not", selector);4371 },4372 4373 filter: function( selector ) {4374 return this.pushStack( winnow(this, selector, true), "filter", selector );4375 },4376 4377 is: function( selector ) {4378 return !!selector && jQuery.filter( selector, this ).length > 0;4379 },4380 4381 closest: function( selectors, context ) {4382 var ret = [], i, l, cur = this[0];4383 4384 if ( jQuery.isArray( selectors ) ) {4385 var match, selector,4386 matches = {},4387 level = 1;4388 4389 if ( cur && selectors.length ) {4390 for ( i = 0, l = selectors.length; i < l; i++ ) {4391 selector = selectors[i];4392 4393 if ( !matches[selector] ) {4394 matches[selector] = jQuery.expr.match.POS.test( selector ) ? 4395 jQuery( selector, context || this.context ) :4396 selector;4397 }4398 }4399 4400 while ( cur && cur.ownerDocument && cur !== context ) {4401 for ( selector in matches ) {4402 match = matches[selector];4403 4404 if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {4405 ret.push({ selector: selector, elem: cur, level: level });4406 }4407 }4408 4409 cur = cur.parentNode;4410 level++;4411 }4412 }4413 4414 return ret;4415 }4416 4417 var pos = POS.test( selectors ) ? 4418 jQuery( selectors, context || this.context ) : null;4419 4420 for ( i = 0, l = this.length; i < l; i++ ) {4421 cur = this[i];4422 4423 while ( cur ) {4424 if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {4425 ret.push( cur );4426 break;4427 4428 } else {4429 cur = cur.parentNode;4430 if ( !cur || !cur.ownerDocument || cur === context ) {4431 break;4432 }4433 }4434 }4435 }4436 4437 ret = ret.length > 1 ? jQuery.unique(ret) : ret;4438 4439 return this.pushStack( ret, "closest", selectors );4440 },4441 4442 // Determine the position of an element within4443 // the matched set of elements4444 index: function( elem ) {4445 if ( !elem || typeof elem === "string" ) {4446 return jQuery.inArray( this[0],4447 // If it receives a string, the selector is used4448 // If it receives nothing, the siblings are used4449 elem ? jQuery( elem ) : this.parent().children() );4450 }4451 // Locate the position of the desired element4452 return jQuery.inArray(4453 // If it receives a jQuery object, the first element is used4454 elem.jquery ? elem[0] : elem, this );4455 },4456 4457 add: function( selector, context ) {4458 var set = typeof selector === "string" ?4459 jQuery( selector, context || this.context ) :4460 jQuery.makeArray( selector ),4461 all = jQuery.merge( this.get(), set );4462 4463 return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?4464 all :4465 jQuery.unique( all ) );4466 },4467 4468 andSelf: function() {4469 return this.add( this.prevObject );4470 }4471 });4472 4473 // A painfully simple check to see if an element is disconnected4474 // from a document (should be improved, where feasible).4475 function isDisconnected( node ) {4476 return !node || !node.parentNode || node.parentNode.nodeType === 11;4477 }4478 4479 jQuery.each({4480 parent: function( elem ) {4481 var parent = elem.parentNode;4482 return parent && parent.nodeType !== 11 ? parent : null;4483 },4484 parents: function( elem ) {4485 return jQuery.dir( elem, "parentNode" );4486 },4487 parentsUntil: function( elem, i, until ) {4488 return jQuery.dir( elem, "parentNode", until );4489 },4490 next: function( elem ) {4491 return jQuery.nth( elem, 2, "nextSibling" );4492 },4493 prev: function( elem ) {4494 return jQuery.nth( elem, 2, "previousSibling" );4495 },4496 nextAll: function( elem ) {4497 return jQuery.dir( elem, "nextSibling" );4498 },4499 prevAll: function( elem ) {4500 return jQuery.dir( elem, "previousSibling" );4501 },4502 nextUntil: function( elem, i, until ) {4503 return jQuery.dir( elem, "nextSibling", until );4504 },4505 prevUntil: function( elem, i, until ) {4506 return jQuery.dir( elem, "previousSibling", until );4507 },4508 siblings: function( elem ) {4509 return jQuery.sibling( elem.parentNode.firstChild, elem );4510 },4511 children: function( elem ) {4512 return jQuery.sibling( elem.firstChild );4513 },4514 contents: function( elem ) {4515 return jQuery.nodeName( elem, "iframe" ) ?4516 elem.contentDocument || elem.contentWindow.document :4517 jQuery.makeArray( elem.childNodes );4518 }4519 }, function( name, fn ) {4520 jQuery.fn[ name ] = function( until, selector ) {4521 var ret = jQuery.map( this, fn, until );4522 4523 if ( !runtil.test( name ) ) {4524 selector = until;4525 }4526 4527 if ( selector && typeof selector === "string" ) {4528 ret = jQuery.filter( selector, ret );4529 }4530 4531 ret = this.length > 1 ? jQuery.unique( ret ) : ret;4532 4533 if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {4534 ret = ret.reverse();4535 }4536 4537 return this.pushStack( ret, name, slice.call(arguments).join(",") );4538 };4539 });4540 4541 jQuery.extend({4542 filter: function( expr, elems, not ) {4543 if ( not ) {4544 expr = ":not(" + expr + ")";4545 }4546 4547 return elems.length === 1 ?4548 jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :4549 jQuery.find.matches(expr, elems);4550 },4551 4552 dir: function( elem, dir, until ) {4553 var matched = [],4554 cur = elem[ dir ];4555 4556 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {4557 if ( cur.nodeType === 1 ) {4558 matched.push( cur );4559 }4560 cur = cur[dir];4561 }4562 return matched;4563 },4564 4565 nth: function( cur, result, dir, elem ) {4566 result = result || 1;4567 var num = 0;4568 4569 for ( ; cur; cur = cur[dir] ) {4570 if ( cur.nodeType === 1 && ++num === result ) {4571 break;4572 }4573 }4574 4575 return cur;4576 },4577 4578 sibling: function( n, elem ) {4579 var r = [];4580 4581 for ( ; n; n = n.nextSibling ) {4582 if ( n.nodeType === 1 && n !== elem ) {4583 r.push( n );4584 }4585 }4586 4587 return r;4588 }4589 });4590 4591 // Implement the identical functionality for filter and not4592 function winnow( elements, qualifier, keep ) {4593 if ( jQuery.isFunction( qualifier ) ) {4594 return jQuery.grep(elements, function( elem, i ) {4595 var retVal = !!qualifier.call( elem, i, elem );4596 return retVal === keep;4597 });4598 4599 } else if ( qualifier.nodeType ) {4600 return jQuery.grep(elements, function( elem, i ) {4601 return (elem === qualifier) === keep;4602 });4603 4604 } else if ( typeof qualifier === "string" ) {4605 var filtered = jQuery.grep(elements, function( elem ) {4606 return elem.nodeType === 1;4607 });4608 4609 if ( isSimple.test( qualifier ) ) {4610 return jQuery.filter(qualifier, filtered, !keep);4611 } else {4612 qualifier = jQuery.filter( qualifier, filtered );4613 }4614 }4615 4616 return jQuery.grep(elements, function( elem, i ) {4617 return (jQuery.inArray( elem, qualifier ) >= 0) === keep;4618 });4619 }4620 4621 4622 4623 4624 var rinlinejQuery = / jQuery/d+="(?:/d+|null)"/g,4625 rleadingWhitespace = /^/s+/,4626 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([/w:]+)[^>]*)//>/ig,4627 rtagName = /<([/w:]+)/,4628 rtbody = /i,4629 rhtml = /<|&#?/w+;/,4630 rnocache = /<(?:script|object|embed|option|style)/i,4631 // checked="checked" or checked (html5)4632 rchecked = /checked/s*(?:[^=]|=/s*.checked.)/i,4633 raction = //=([^="'>/s]+//)>/g,4634 wrapMap = {4635 option: [ 1, "" ],4636 legend: [ 1, "
", "
" ],4637 thead: [ 1, "", "
" ],4638 tr: [ 2, "", "
" ],4639 td: [ 3, "", "
" ],4640 col: [ 2, "", "
" ],4641 area: [ 1, "", "" ],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 and

你可能感兴趣的:(前端开发)