vendor: 6,970 bytes, lines 1-273
1/*! 2 * jQuery JavaScript Library v1.11.2 3 * http://jquery.com/ 4 * 5 * Includes Sizzle.js 6 * http://sizzlejs.com/ 7 * 8 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors 9 * Released under the MIT license 10 * http://jquery.org/license 11 * 12 * Date: 2014-12-17T15:27Z 13 */ 14 15(function( global, factory ) { 16 17 if ( typeof module === "object" && typeof module.exports === "object" ) { 18 // For CommonJS and CommonJS-like environments where a proper window is present, 19 // execute the factory and get jQuery 20 // For environments that do not inherently posses a window with a document 21 // (such as Node.js), expose a jQuery-making factory as module.exports 22 // This accentuates the need for the creation of a real window 23 // e.g. var jQuery = require("jquery")(window); 24 // See ticket #14549 for more info 25 module.exports = global.document ? 26 factory( global, true ) : 27 function( w ) { 28 if ( !w.document ) { 29 throw new Error( "jQuery requires a window with a document" ); 30 } 31 return factory( w ); 32 }; 33 } else { 34 factory( global ); 35 } 36 37// Pass this if window is not defined yet 38}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { 39 40// Can't do this because several apps including ASP.NET trace 41// the stack via arguments.caller.callee and Firefox dies if 42// you try to trace through "use strict" call chains. (#13335) 43// Support: Firefox 18+ 44// 45 46var deletedIds = []; 47 48var slice = deletedIds.slice; 49 50var concat = deletedIds.concat; 51 52var push = deletedIds.push; 53 54var indexOf = deletedIds.indexOf; 55 56var class2type = {}; 57 58var toString = class2type.toString; 59 60var hasOwn = class2type.hasOwnProperty; 61 62var support = {}; 63 64 65 66var 67 version = "1.11.2", 68 69 // Define a local copy of jQuery 70 jQuery = function( selector, context ) { 71 // The jQuery object is actually just the init constructor 'enhanced' 72 // Need init if jQuery is called (just allow error to be thrown if not included) 73 return new jQuery.fn.init( selector, context ); 74 }, 75 76 // Support: Android<4.1, IE<9 77 // Make sure we trim BOM and NBSP 78 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, 79 80 // Matches dashed string for camelizing 81 rmsPrefix = /^-ms-/, 82 rdashAlpha = /-([\da-z])/gi, 83 84 // Used by jQuery.camelCase as callback to replace() 85 fcamelCase = function( all, letter ) { 86 return letter.toUpperCase(); 87 }; 88 89jQuery.fn = jQuery.prototype = { 90 // The current version of jQuery being used 91 jquery: version, 92 93 constructor: jQuery, 94 95 // Start with an empty selector 96 selector: "", 97 98 // The default length of a jQuery object is 0 99 length: 0, 100 101 toArray: function() { 102 return slice.call( this ); 103 }, 104 105 // Get the Nth element in the matched element set OR 106 // Get the whole matched element set as a clean array 107 get: function( num ) { 108 return num != null ? 109 110 // Return just the one element from the set 111 ( num < 0 ? this[ num + this.length ] : this[ num ] ) : 112 113 // Return all the elements in a clean array 114 slice.call( this ); 115 }, 116 117 // Take an array of elements and push it onto the stack 118 // (returning the new matched element set) 119 pushStack: function( elems ) { 120 121 // Build a new jQuery matched element set 122 var ret = jQuery.merge( this.constructor(), elems ); 123 124 // Add the old object onto the stack (as a reference) 125 ret.prevObject = this; 126 ret.context = this.context; 127 128 // Return the newly-formed element set 129 return ret; 130 }, 131 132 // Execute a callback for every element in the matched set. 133 // (You can seed the arguments with an array of args, but this is 134 // only used internally.) 135 each: function( callback, args ) { 136 return jQuery.each( this, callback, args ); 137 }, 138 139 map: function( callback ) { 140 return this.pushStack( jQuery.map(this, function( elem, i ) { 141 return callback.call( elem, i, elem ); 142 })); 143 }, 144 145 slice: function() { 146 return this.pushStack( slice.apply( this, arguments ) ); 147 }, 148 149 first: function() { 150 return this.eq( 0 ); 151 }, 152 153 last: function() { 154 return this.eq( -1 ); 155 }, 156 157 eq: function( i ) { 158 var len = this.length, 159 j = +i + ( i < 0 ? len : 0 ); 160 return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); 161 }, 162 163 end: function() { 164 return this.prevObject || this.constructor(null); 165 }, 166 167 // For internal use only. 168 // Behaves like an Array's method, not like a jQuery method. 169 push: push, 170 sort: deletedIds.sort, 171 splice: deletedIds.splice 172}; 173 174jQuery.extend = jQuery.fn.extend = function() { 175 var src, copyIsArray, copy, name, options, clone, 176 target = arguments[0] || {}, 177 i = 1, 178 length = arguments.length, 179 deep = false; 180 181 // Handle a deep copy situation 182 if ( typeof target === "boolean" ) { 183 deep = target; 184 185 // skip the boolean and the target 186 target = arguments[ i ] || {}; 187 i++; 188 } 189 190 // Handle case when target is a string or something (possible in deep copy) 191 if ( typeof target !== "object" && !jQuery.isFunction(target) ) { 192 target = {}; 193 } 194 195 // extend jQuery itself if only one argument is passed 196 if ( i === length ) { 197 target = this; 198 i--; 199 } 200 201 for ( ; i < length; i++ ) { 202 // Only deal with non-null/undefined values 203 if ( (options = arguments[ i ]) != null ) { 204 // Extend the base object 205 for ( name in options ) { 206 src = target[ name ]; 207 copy = options[ name ]; 208 209 // Prevent never-ending loop 210 if ( target === copy ) { 211 continue; 212 } 213 214 // Recurse if we're merging plain objects or arrays 215 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { 216 if ( copyIsArray ) { 217 copyIsArray = false; 218 clone = src && jQuery.isArray(src) ? src : []; 219 220 } else { 221 clone = src && jQuery.isPlainObject(src) ? src : {}; 222 } 223 224 // Never move original objects, clone them 225 target[ name ] = jQuery.extend( deep, clone, copy ); 226 227 // Don't bring in undefined values 228 } else if ( copy !== undefined ) { 229 target[ name ] = copy; 230 } 231 } 232 } 233 } 234 235 // Return the modified object 236 return target; 237}; 238 239jQuery.extend({ 240 // Unique for each copy of jQuery on the page 241 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), 242 243 // Assume jQuery is ready without the ready module 244 isReady: true, 245 246 error: function( msg ) { 247 throw new Error( msg ); 248 }, 249 250 noop: function() {}, 251 252 // See test/unit/core.js for details concerning isFunction. 253 // Since version 1.3, DOM methods and functions like alert 254 // aren't supported. They return false on IE (#2968). 255 isFunction: function( obj ) { 256 return jQuery.type(obj) === "function"; 257 }, 258 259 isArray: Array.isArray || function( obj ) { 260 return jQuery.type(obj) === "array"; 261 }, 262 263 isWindow: function( obj ) { 264 /* jshint eqeqeq: false */ 265 return obj != null && obj == obj.window; 266 }, 267 268 isNumeric: function( obj ) { 269 // parseFloat NaNs numeric-cast false positives (null|true|false|"") 270 // ...but misinterprets leading-number strings, particularly hex literals ("0x...") 271 // subtraction forces infinities to NaN 272 // adding 1 corrects loss of precision from parseFloat (#15100) 273 return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1
vendor: 6,809 bytes, lines 273-576
273) >= 0; 274 }, 275 276 isEmptyObject: function( obj ) { 277 var name; 278 for ( name in obj ) { 279 return false; 280 } 281 return true; 282 }, 283 284 isPlainObject: function( obj ) { 285 var key; 286 287 // Must be an Object. 288 // Because of IE, we also have to check the presence of the constructor property. 289 // Make sure that DOM nodes and window objects don't pass through, as well 290 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { 291 return false; 292 } 293 294 try { 295 // Not own constructor property must be Object 296 if ( obj.constructor && 297 !hasOwn.call(obj, "constructor") && 298 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { 299 return false; 300 } 301 } catch ( e ) { 302 // IE8,9 Will throw exceptions on certain host objects #9897 303 return false; 304 } 305 306 // Support: IE<9 307 // Handle iteration over inherited properties before own properties. 308 if ( support.ownLast ) { 309 for ( key in obj ) { 310 return hasOwn.call( obj, key ); 311 } 312 } 313 314 // Own properties are enumerated firstly, so to speed up, 315 // if last one is own, then all properties are own. 316 for ( key in obj ) {} 317 318 return key === undefined || hasOwn.call( obj, key ); 319 }, 320 321 type: function( obj ) { 322 if ( obj == null ) { 323 return obj + ""; 324 } 325 return typeof obj === "object" || typeof obj === "function" ? 326 class2type[ toString.call(obj) ] || "object" : 327 typeof obj; 328 }, 329 330 // Evaluates a script in a global context 331 // Workarounds based on findings by Jim Driscoll 332 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context 333 globalEval: function( data ) { 334 if ( data && jQuery.trim( data ) ) { 335 // We use execScript on Internet Explorer 336 // We use an anonymous function so that context is window 337 // rather than jQuery in Firefox 338 ( window.execScript || function( data ) { 339 window[ "eval" ].call( window, data ); 340 } )( data ); 341 } 342 }, 343 344 // Convert dashed to camelCase; used by the css and data modules 345 // Microsoft forgot to hump their vendor prefix (#9572) 346 camelCase: function( string ) { 347 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); 348 }, 349 350 nodeName: function( elem, name ) { 351 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); 352 }, 353 354 // args is for internal usage only 355 each: function( obj, callback, args ) { 356 var value, 357 i = 0, 358 length = obj.length, 359 isArray = isArraylike( obj ); 360 361 if ( args ) { 362 if ( isArray ) { 363 for ( ; i < length; i++ ) { 364 value = callback.apply( obj[ i ], args ); 365 366 if ( value === false ) { 367 break; 368 } 369 } 370 } else { 371 for ( i in obj ) { 372 value = callback.apply( obj[ i ], args ); 373 374 if ( value === false ) { 375 break; 376 } 377 } 378 } 379 380 // A special, fast, case for the most common use of each 381 } else { 382 if ( isArray ) { 383 for ( ; i < length; i++ ) { 384 value = callback.call( obj[ i ], i, obj[ i ] ); 385 386 if ( value === false ) { 387 break; 388 } 389 } 390 } else { 391 for ( i in obj ) { 392 value = callback.call( obj[ i ], i, obj[ i ] ); 393 394 if ( value === false ) { 395 break; 396 } 397 } 398 } 399 } 400 401 return obj; 402 }, 403 404 // Support: Android<4.1, IE<9 405 trim: function( text ) { 406 return text == null ? 407 "" : 408 ( text + "" ).replace( rtrim, "" ); 409 }, 410 411 // results is for internal usage only 412 makeArray: function( arr, results ) { 413 var ret = results || []; 414 415 if ( arr != null ) { 416 if ( isArraylike( Object(arr) ) ) { 417 jQuery.merge( ret, 418 typeof arr === "string" ? 419 [ arr ] : arr 420 ); 421 } else { 422 push.call( ret, arr ); 423 } 424 } 425 426 return ret; 427 }, 428 429 inArray: function( elem, arr, i ) { 430 var len; 431 432 if ( arr ) { 433 if ( indexOf ) { 434 return indexOf.call( arr, elem, i ); 435 } 436 437 len = arr.length; 438 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; 439 440 for ( ; i < len; i++ ) { 441 // Skip accessing in sparse arrays 442 if ( i in arr && arr[ i ] === elem ) { 443 return i; 444 } 445 } 446 } 447 448 return -1; 449 }, 450 451 merge: function( first, second ) { 452 var len = +second.length, 453 j = 0, 454 i = first.length; 455 456 while ( j < len ) { 457 first[ i++ ] = second[ j++ ]; 458 } 459 460 // Support: IE<9 461 // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) 462 if ( len !== len ) { 463 while ( second[j] !== undefined ) { 464 first[ i++ ] = second[ j++ ]; 465 } 466 } 467 468 first.length = i; 469 470 return first; 471 }, 472 473 grep: function( elems, callback, invert ) { 474 var callbackInverse, 475 matches = [], 476 i = 0, 477 length = elems.length, 478 callbackExpect = !invert; 479 480 // Go through the array, only saving the items 481 // that pass the validator function 482 for ( ; i < length; i++ ) { 483 callbackInverse = !callback( elems[ i ], i ); 484 if ( callbackInverse !== callbackExpect ) { 485 matches.push( elems[ i ] ); 486 } 487 } 488 489 return matches; 490 }, 491 492 // arg is for internal usage only 493 map: function( elems, callback, arg ) { 494 var value, 495 i = 0, 496 length = elems.length, 497 isArray = isArraylike( elems ), 498 ret = []; 499 500 // Go through the array, translating each of the items to their new values 501 if ( isArray ) { 502 for ( ; i < length; i++ ) { 503 value = callback( elems[ i ], i, arg ); 504 505 if ( value != null ) { 506 ret.push( value ); 507 } 508 } 509 510 // Go through every key on the object, 511 } else { 512 for ( i in elems ) { 513 value = callback( elems[ i ], i, arg ); 514 515 if ( value != null ) { 516 ret.push( value ); 517 } 518 } 519 } 520 521 // Flatten any nested arrays 522 return concat.apply( [], ret ); 523 }, 524 525 // A global GUID counter for objects 526 guid: 1, 527 528 // Bind a function to a context, optionally partially applying any 529 // arguments. 530 proxy: function( fn, context ) { 531 var args, proxy, tmp; 532 533 if ( typeof context === "string" ) { 534 tmp = fn[ context ]; 535 context = fn; 536 fn = tmp; 537 } 538 539 // Quick check to determine if target is callable, in the spec 540 // this throws a TypeError, but we will just return undefined. 541 if ( !jQuery.isFunction( fn ) ) { 542 return undefined; 543 } 544 545 // Simulated bind 546 args = slice.call( arguments, 2 ); 547 proxy = function() { 548 return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); 549 }; 550 551 // Set the guid of unique handler to the same of original handler, so it can be removed 552 proxy.guid = fn.guid = fn.guid || jQuery.guid++; 553 554 return proxy; 555 }, 556 557 now: function() { 558 return +( new Date() ); 559 }, 560 561 // jQuery.support is not used in Core but other projects attach their 562 // properties to it so it needs to exist. 563 support: support 564}); 565 566// Populate the class2type map 567jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { 568 class2type[ "[object " + name + "]" ] = name.toLowerCase(); 569}); 570 571function isArraylike( obj ) { 572 var length = obj.length, 573 type = jQuery.type( obj ); 574 575 if ( type === "function" || jQuery.isWindow( obj ) ) { 576 return false;
vendor: 27,621 bytes, lines 577-1539
577 } 578 579 if ( obj.nodeType === 1 && length ) { 580 return true; 581 } 582 583 return type === "array" || length === 0 || 584 typeof length === "number" && length > 0 && ( length - 1 ) in obj; 585} 586var Sizzle = 587/*! 588 * Sizzle CSS Selector Engine v2.2.0-pre 589 * http://sizzlejs.com/ 590 * 591 * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors 592 * Released under the MIT license 593 * http://jquery.org/license 594 * 595 * Date: 2014-12-16 596 */ 597(function( window ) { 598 599var i, 600 support, 601 Expr, 602 getText, 603 isXML, 604 tokenize, 605 compile, 606 select, 607 outermostContext, 608 sortInput, 609 hasDuplicate, 610 611 // Local document vars 612 setDocument, 613 document, 614 docElem, 615 documentIsHTML, 616 rbuggyQSA, 617 rbuggyMatches, 618 matches, 619 contains, 620 621 // Instance-specific data 622 expando = "sizzle" + 1 * new Date(), 623 preferredDoc = window.document, 624 dirruns = 0, 625 done = 0, 626 classCache = createCache(), 627 tokenCache = createCache(), 628 compilerCache = createCache(), 629 sortOrder = function( a, b ) { 630 if ( a === b ) { 631 hasDuplicate = true; 632 } 633 return 0; 634 }, 635 636 // General-purpose constants 637 MAX_NEGATIVE = 1 << 31, 638 639 // Instance methods 640 hasOwn = ({}).hasOwnProperty, 641 arr = [], 642 pop = arr.pop, 643 push_native = arr.push, 644 push = arr.push, 645 slice = arr.slice, 646 // Use a stripped-down indexOf as it's faster than native 647 // http://jsperf.com/thor-indexof-vs-for/5 648 indexOf = function( list, elem ) { 649 var i = 0, 650 len = list.length; 651 for ( ; i < len; i++ ) { 652 if ( list[i] === elem ) { 653 return i; 654 } 655 } 656 return -1; 657 }, 658 659 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", 660 661 // Regular expressions 662 663 // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace 664 whitespace = "[\\x20\\t\\r\\n\\f]", 665 // http://www.w3.org/TR/css3-syntax/#characters 666 characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", 667 668 // Loosely modeled on CSS identifier characters 669 // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors 670 // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier 671 identifier = characterEncoding.replace( "w", "w#" ), 672 673 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors 674 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + 675 // Operator (capture 2) 676 "*([*^$|!~]?=)" + whitespace + 677 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" 678 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + 679 "*\\]", 680 681 pseudos = ":(" + characterEncoding + ")(?:\\((" + 682 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: 683 // 1. quoted (capture 3; capture 4 or capture 5) 684 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + 685 // 2. simple (capture 6) 686 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + 687 // 3. anything else (capture 2) 688 ".*" + 689 ")\\)|)", 690 691 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter 692 rwhitespace = new RegExp( whitespace + "+", "g" ), 693 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), 694 695 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), 696 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), 697 698 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), 699 700 rpseudo = new RegExp( pseudos ), 701 ridentifier = new RegExp( "^" + identifier + "$" ), 702 703 matchExpr = { 704 "ID": new RegExp( "^#(" + characterEncoding + ")" ), 705 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), 706 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), 707 "ATTR": new RegExp( "^" + attributes ), 708 "PSEUDO": new RegExp( "^" + pseudos ), 709 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + 710 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + 711 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), 712 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), 713 // For use in libraries implementing .is() 714 // We use this for POS matching in `select` 715 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + 716 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) 717 }, 718 719 rinputs = /^(?:input|select|textarea|button)$/i, 720 rheader = /^h\d$/i, 721 722 rnative = /^[^{]+\{\s*\[native \w/, 723 724 // Easily-parseable/retrievable ID or TAG or CLASS selectors 725 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, 726 727 rsibling = /[+~]/, 728 rescape = /'|\\/g, 729 730 // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters 731 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), 732 funescape = function( _, escaped, escapedWhitespace ) { 733 var high = "0x" + escaped - 0x10000; 734 // NaN means non-codepoint 735 // Support: Firefox<24 736 // Workaround erroneous numeric interpretation of +"0x" 737 return high !== high || escapedWhitespace ? 738 escaped : 739 high < 0 ? 740 // BMP codepoint 741 String.fromCharCode( high + 0x10000 ) : 742 // Supplemental Plane codepoint (surrogate pair) 743 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); 744 }, 745 746 // Used for iframes 747 // See setDocument() 748 // Removing the function wrapper causes a "Permission Denied" 749 // error in IE 750 unloadHandler = function() { 751 setDocument(); 752 }; 753 754// Optimize for push.apply( _, NodeList ) 755try { 756 push.apply( 757 (arr = slice.call( preferredDoc.childNodes )), 758 preferredDoc.childNodes 759 ); 760 // Support: Android<4.0 761 // Detect silently failing push.apply 762 arr[ preferredDoc.childNodes.length ].nodeType; 763} catch ( e ) { 764 push = { apply: arr.length ? 765 766 // Leverage slice if possible 767 function( target, els ) { 768 push_native.apply( target, slice.call(els) ); 769 } : 770 771 // Support: IE<9 772 // Otherwise append directly 773 function( target, els ) { 774 var j = target.length, 775 i = 0; 776 // Can't trust NodeList.length 777 while ( (target[j++] = els[i++]) ) {} 778 target.length = j - 1; 779 } 780 }; 781} 782 783function Sizzle( selector, context, results, seed ) { 784 var match, elem, m, nodeType, 785 // QSA vars 786 i, groups, old, nid, newContext, newSelector; 787 788 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { 789 setDocument( context ); 790 } 791 792 context = context || document; 793 results = results || []; 794 nodeType = context.nodeType; 795 796 if ( typeof selector !== "string" || !selector || 797 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { 798 799 return results; 800 } 801 802 if ( !seed && documentIsHTML ) { 803 804 // Try to shortcut find operations when possible (e.g., not under DocumentFragment) 805 if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { 806 // Speed-up: Sizzle("#ID") 807 if ( (m = match[1]) ) { 808 if ( nodeType === 9 ) { 809 elem = context.getElementById( m ); 810 // Check parentNode to catch when Blackberry 4.6 returns 811 // nodes that are no longer in the document (jQuery #6963) 812 if ( elem && elem.parentNode ) { 813 // Handle the case where IE, Opera, and Webkit return items 814 // by name instead of ID 815 if ( elem.id === m ) { 816 results.push( elem ); 817 return results; 818 } 819 } else { 820 return results; 821 } 822 } else { 823 // Context is not a document 824 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && 825 contains( context, elem ) && elem.id === m ) { 826 results.push( elem ); 827 return results; 828 } 829 } 830 831 // Speed-up: Sizzle("TAG") 832 } else if ( match[2] ) { 833 push.apply( results, context.getElementsByTagName( selector ) ); 834 return results; 835 836 // Speed-up: Sizzle(".CLASS") 837 } else if ( (m = match[3]) && support.getElementsByClassName ) { 838 push.apply( results, context.getElementsByClassName( m ) ); 839 return results; 840 } 841 } 842 843 // QSA path 844 if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { 845 nid = old = expando; 846 newContext = context; 847 newSelector = nodeType !== 1 && selector; 848 849 // qSA works strangely on Element-rooted queries 850 // We can work around this by specifying an extra ID on the root 851 // and working up from there (Thanks to Andrew Dupont for the technique) 852 // IE 8 doesn't work on object elements 853 if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { 854 groups = tokenize( selector ); 855 856 if ( (old = context.getAttribute("id")) ) { 857 nid = old.replace( rescape, "\\$&" ); 858 } else { 859 context.setAttribute( "id", nid ); 860 } 861 nid = "[id='" + nid + "'] "; 862 863 i = groups.length; 864 while ( i-- ) { 865 groups[i] = nid + toSelector( groups[i] ); 866 } 867 newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; 868 newSelector = groups.join(","); 869 } 870 871 if ( newSelector ) { 872 try { 873 push.apply( results, 874 newContext.querySelectorAll( newSelector ) 875 ); 876 return results; 877 } catch(qsaError) { 878 } finally { 879 if ( !old ) { 880 context.removeAttribute("id"); 881 } 882 } 883 } 884 } 885 } 886 887 // All others 888 return select( selector.replace( rtrim, "$1" ), context, results, seed ); 889} 890 891/** 892 * Create key-value caches of limited size 893 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with 894 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) 895 * deleting the oldest entry 896 */ 897function createCache() { 898 var keys = []; 899 900 function cache( key, value ) { 901 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) 902 if ( keys.push( key + " " ) > Expr.cacheLength ) { 903 // Only keep the most recent entries 904 delete cache[ keys.shift() ]; 905 } 906 return (cache[ key + " " ] = value); 907 } 908 return cache; 909} 910 911/** 912 * Mark a function for special use by Sizzle 913 * @param {Function} fn The function to mark 914 */ 915function markFunction( fn ) { 916 fn[ expando ] = true; 917 return fn; 918} 919 920/** 921 * Support testing using an element 922 * @param {Function} fn Passed the created div and expects a boolean result 923 */ 924function assert( fn ) { 925 var div = document.createElement("div"); 926 927 try { 928 return !!fn( div ); 929 } catch (e) { 930 return false; 931 } finally { 932 // Remove from its parent by default 933 if ( div.parentNode ) { 934 div.parentNode.removeChild( div ); 935 } 936 // release memory in IE 937 div = null; 938 } 939} 940 941/** 942 * Adds the same handler for all of the specified attrs 943 * @param {String} attrs Pipe-separated list of attributes 944 * @param {Function} handler The method that will be applied 945 */ 946function addHandle( attrs, handler ) { 947 var arr = attrs.split("|"), 948 i = attrs.length; 949 950 while ( i-- ) { 951 Expr.attrHandle[ arr[i] ] = handler; 952 } 953} 954 955/** 956 * Checks document order of two siblings 957 * @param {Element} a 958 * @param {Element} b 959 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b 960 */ 961function siblingCheck( a, b ) { 962 var cur = b && a, 963 diff = cur && a.nodeType === 1 && b.nodeType === 1 && 964 ( ~b.sourceIndex || MAX_NEGATIVE ) - 965 ( ~a.sourceIndex || MAX_NEGATIVE ); 966 967 // Use IE sourceIndex if available on both nodes 968 if ( diff ) { 969 return diff; 970 } 971 972 // Check if b follows a 973 if ( cur ) { 974 while ( (cur = cur.nextSibling) ) { 975 if ( cur === b ) { 976 return -1; 977 } 978 } 979 } 980 981 return a ? 1 : -1; 982} 983 984/** 985 * Returns a function to use in pseudos for input types 986 * @param {String} type 987 */ 988function createInputPseudo( type ) { 989 return function( elem ) { 990 var name = elem.nodeName.toLowerCase(); 991 return name === "input" && elem.type === type; 992 }; 993} 994 995/** 996 * Returns a function to use in pseudos for buttons 997 * @param {String} type 998 */ 999function createButtonPseudo( type ) { 1000 return function( elem ) { 1001 var name = elem.nodeName.toLowerCase(); 1002 return (name === "input" || name === "button") && elem.type === type; 1003 }; 1004} 1005 1006/** 1007 * Returns a function to use in pseudos for positionals 1008 * @param {Function} fn 1009 */ 1010function createPositionalPseudo( fn ) { 1011 return markFunction(function( argument ) { 1012 argument = +argument; 1013 return markFunction(function( seed, matches ) { 1014 var j, 1015 matchIndexes = fn( [], seed.length, argument ), 1016 i = matchIndexes.length; 1017 1018 // Match elements found at the specified indexes 1019 while ( i-- ) { 1020 if ( seed[ (j = matchIndexes[i]) ] ) { 1021 seed[j] = !(matches[j] = seed[j]); 1022 } 1023 } 1024 }); 1025 }); 1026} 1027 1028/** 1029 * Checks a node for validity as a Sizzle context 1030 * @param {Element|Object=} context 1031 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value 1032 */ 1033function testContext( context ) { 1034 return context && typeof context.getElementsByTagName !== "undefined" && context; 1035} 1036 1037// Expose support vars for convenience 1038support = Sizzle.support = {}; 1039 1040/** 1041 * Detects XML nodes 1042 * @param {Element|Object} elem An element or a document 1043 * @returns {Boolean} True iff elem is a non-HTML XML node 1044 */ 1045isXML = Sizzle.isXML = function( elem ) { 1046 // documentElement is verified for cases where it doesn't yet exist 1047 // (such as loading iframes in IE - #4833) 1048 var documentElement = elem && (elem.ownerDocument || elem).documentElement; 1049 return documentElement ? documentElement.nodeName !== "HTML" : false; 1050}; 1051 1052/** 1053 * Sets document-related variables once based on the current document 1054 * @param {Element|Object} [doc] An element or document object to use to set the document 1055 * @returns {Object} Returns the current document 1056 */ 1057setDocument = Sizzle.setDocument = function( node ) { 1058 var hasCompare, parent, 1059 doc = node ? node.ownerDocument || node : preferredDoc; 1060 1061 // If no document and documentElement is available, return 1062 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { 1063 return document; 1064 } 1065 1066 // Set our document 1067 document = doc; 1068 docElem = doc.documentElement; 1069 parent = doc.defaultView; 1070 1071 // Support: IE>8 1072 // If iframe document is assigned to "document" variable and if iframe has been reloaded, 1073 // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 1074 // IE6-8 do not support the defaultView property so parent will be undefined 1075 if ( parent && parent !== parent.top ) { 1076 // IE11 does not have attachEvent, so all must suffer 1077 if ( parent.addEventListener ) { 1078 parent.addEventListener( "unload", unloadHandler, false ); 1079 } else if ( parent.attachEvent ) { 1080 parent.attachEvent( "onunload", unloadHandler ); 1081 } 1082 } 1083 1084 /* Support tests 1085 ---------------------------------------------------------------------- */ 1086 documentIsHTML = !isXML( doc ); 1087 1088 /* Attributes 1089 ---------------------------------------------------------------------- */ 1090 1091 // Support: IE<8 1092 // Verify that getAttribute really returns attributes and not properties 1093 // (excepting IE8 booleans) 1094 support.attributes = assert(function( div ) { 1095 div.className = "i"; 1096 return !div.getAttribute("className"); 1097 }); 1098 1099 /* getElement(s)By* 1100 ---------------------------------------------------------------------- */ 1101 1102 // Check if getElementsByTagName("*") returns only elements 1103 support.getElementsByTagName = assert(function( div ) { 1104 div.appendChild( doc.createComment("") ); 1105 return !div.getElementsByTagName("*").length; 1106 }); 1107 1108 // Support: IE<9 1109 support.getElementsByClassName = rnative.test( doc.getElementsByClassName ); 1110 1111 // Support: IE<10 1112 // Check if getElementById returns elements by name 1113 // The broken getElementById methods don't pick up programatically-set names, 1114 // so use a roundabout getElementsByName test 1115 support.getById = assert(function( div ) { 1116 docElem.appendChild( div ).id = expando; 1117 return !doc.getElementsByName || !doc.getElementsByName( expando ).length; 1118 }); 1119 1120 // ID find and filter 1121 if ( support.getById ) { 1122 Expr.find["ID"] = function( id, context ) { 1123 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { 1124 var m = context.getElementById( id ); 1125 // Check parentNode to catch when Blackberry 4.6 returns 1126 // nodes that are no longer in the document #6963 1127 return m && m.parentNode ? [ m ] : []; 1128 } 1129 }; 1130 Expr.filter["ID"] = function( id ) { 1131 var attrId = id.replace( runescape, funescape ); 1132 return function( elem ) { 1133 return elem.getAttribute("id") === attrId; 1134 }; 1135 }; 1136 } else { 1137 // Support: IE6/7 1138 // getElementById is not reliable as a find shortcut 1139 delete Expr.find["ID"]; 1140 1141 Expr.filter["ID"] = function( id ) { 1142 var attrId = id.replace( runescape, funescape ); 1143 return function( elem ) { 1144 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); 1145 return node && node.value === attrId; 1146 }; 1147 }; 1148 } 1149 1150 // Tag 1151 Expr.find["TAG"] = support.getElementsByTagName ? 1152 function( tag, context ) { 1153 if ( typeof context.getElementsByTagName !== "undefined" ) { 1154 return context.getElementsByTagName( tag ); 1155 1156 // DocumentFragment nodes don't have gEBTN 1157 } else if ( support.qsa ) { 1158 return context.querySelectorAll( tag ); 1159 } 1160 } : 1161 1162 function( tag, context ) { 1163 var elem, 1164 tmp = [], 1165 i = 0, 1166 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too 1167 results = context.getElementsByTagName( tag ); 1168 1169 // Filter out possible comments 1170 if ( tag === "*" ) { 1171 while ( (elem = results[i++]) ) { 1172 if ( elem.nodeType === 1 ) { 1173 tmp.push( elem ); 1174 } 1175 } 1176 1177 return tmp; 1178 } 1179 return results; 1180 }; 1181 1182 // Class 1183 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { 1184 if ( documentIsHTML ) { 1185 return context.getElementsByClassName( className ); 1186 } 1187 }; 1188 1189 /* QSA/matchesSelector 1190 ---------------------------------------------------------------------- */ 1191 1192 // QSA and matchesSelector support 1193 1194 // matchesSelector(:active) reports false when true (IE9/Opera 11.5) 1195 rbuggyMatches = []; 1196 1197 // qSa(:focus) reports false when true (Chrome 21) 1198 // We allow this because of a bug in IE8/9 that throws an error 1199 // whenever `document.activeElement` is accessed on an iframe 1200 // So, we allow :focus to pass through QSA all the time to avoid the IE error 1201 // See http://bugs.jquery.com/ticket/13378 1202 rbuggyQSA = []; 1203 1204 if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { 1205 // Build QSA regex 1206 // Regex strategy adopted from Diego Perini 1207 assert(function( div ) { 1208 // Select is set to empty string on purpose 1209 // This is to test IE's treatment of not explicitly 1210 // setting a boolean content attribute, 1211 // since its presence should be enough 1212 // http://bugs.jquery.com/ticket/12359 1213 docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" + 1214 "<select id='" + expando + "-\f]' msallowcapture=''>" + 1215 "<option selected=''></option></select>"; 1216 1217 // Support: IE8, Opera 11-12.16 1218 // Nothing should be selected when empty strings follow ^= or $= or *= 1219 // The test attribute must be unknown in Opera but "safe" for WinRT 1220 // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section 1221 if ( div.querySelectorAll("[msallowcapture^='']").length ) { 1222 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); 1223 } 1224 1225 // Support: IE8 1226 // Boolean attributes and "value" are not treated correctly 1227 if ( !div.querySelectorAll("[selected]").length ) { 1228 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); 1229 } 1230 1231 // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+ 1232 if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { 1233 rbuggyQSA.push("~="); 1234 } 1235 1236 // Webkit/Opera - :checked should return selected option elements 1237 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 1238 // IE8 throws error here and will not see later tests 1239 if ( !div.querySelectorAll(":checked").length ) { 1240 rbuggyQSA.push(":checked"); 1241 } 1242 1243 // Support: Safari 8+, iOS 8+ 1244 // https://bugs.webkit.org/show_bug.cgi?id=136851 1245 // In-page `selector#id sibing-combinator selector` fails 1246 if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { 1247 rbuggyQSA.push(".#.+[+~]"); 1248 } 1249 }); 1250 1251 assert(function( div ) { 1252 // Support: Windows 8 Native Apps 1253 // The type and name attributes are restricted during .innerHTML assignment 1254 var input = doc.createElement("input"); 1255 input.setAttribute( "type", "hidden" ); 1256 div.appendChild( input ).setAttribute( "name", "D" ); 1257 1258 // Support: IE8 1259 // Enforce case-sensitivity of name attribute 1260 if ( div.querySelectorAll("[name=d]").length ) { 1261 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); 1262 } 1263 1264 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) 1265 // IE8 throws error here and will not see later tests 1266 if ( !div.querySelectorAll(":enabled").length ) { 1267 rbuggyQSA.push( ":enabled", ":disabled" ); 1268 } 1269 1270 // Opera 10-11 does not throw on post-comma invalid pseudos 1271 div.querySelectorAll("*,:x"); 1272 rbuggyQSA.push(",.*:"); 1273 }); 1274 } 1275 1276 if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || 1277 docElem.webkitMatchesSelector || 1278 docElem.mozMatchesSelector || 1279 docElem.oMatchesSelector || 1280 docElem.msMatchesSelector) )) ) { 1281 1282 assert(function( div ) { 1283 // Check to see if it's possible to do matchesSelector 1284 // on a disconnected node (IE 9) 1285 support.disconnectedMatch = matches.call( div, "div" ); 1286 1287 // This should fail with an exception 1288 // Gecko does not error, returns false instead 1289 matches.call( div, "[s!='']:x" ); 1290 rbuggyMatches.push( "!=", pseudos ); 1291 }); 1292 } 1293 1294 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); 1295 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); 1296 1297 /* Contains 1298 ---------------------------------------------------------------------- */ 1299 hasCompare = rnative.test( docElem.compareDocumentPosition ); 1300 1301 // Element contains another 1302 // Purposefully does not implement inclusive descendent 1303 // As in, an element does not contain itself 1304 contains = hasCompare || rnative.test( docElem.contains ) ? 1305 function( a, b ) { 1306 var adown = a.nodeType === 9 ? a.documentElement : a, 1307 bup = b && b.parentNode; 1308 return a === bup || !!( bup && bup.nodeType === 1 && ( 1309 adown.contains ? 1310 adown.contains( bup ) : 1311 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 1312 )); 1313 } : 1314 function( a, b ) { 1315 if ( b ) { 1316 while ( (b = b.parentNode) ) { 1317 if ( b === a ) { 1318 return true; 1319 } 1320 } 1321 } 1322 return false; 1323 }; 1324 1325 /* Sorting 1326 ---------------------------------------------------------------------- */ 1327 1328 // Document order sorting 1329 sortOrder = hasCompare ? 1330 function( a, b ) { 1331 1332 // Flag for duplicate removal 1333 if ( a === b ) { 1334 hasDuplicate = true; 1335 return 0; 1336 } 1337 1338 // Sort on method existence if only one input has compareDocumentPosition 1339 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; 1340 if ( compare ) { 1341 return compare; 1342 } 1343 1344 // Calculate position if both inputs belong to the same document 1345 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? 1346 a.compareDocumentPosition( b ) : 1347 1348 // Otherwise we know they are disconnected 1349 1; 1350 1351 // Disconnected nodes 1352 if ( compare & 1 || 1353 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { 1354 1355 // Choose the first element that is related to our preferred document 1356 if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { 1357 return -1; 1358 } 1359 if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { 1360 return 1; 1361 } 1362 1363 // Maintain original order 1364 return sortInput ? 1365 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 1366 0; 1367 } 1368 1369 return compare & 4 ? -1 : 1; 1370 } : 1371 function( a, b ) { 1372 // Exit early if the nodes are identical 1373 if ( a === b ) { 1374 hasDuplicate = true; 1375 return 0; 1376 } 1377 1378 var cur, 1379 i = 0, 1380 aup = a.parentNode, 1381 bup = b.parentNode, 1382 ap = [ a ], 1383 bp = [ b ]; 1384 1385 // Parentless nodes are either documents or disconnected 1386 if ( !aup || !bup ) { 1387 return a === doc ? -1 : 1388 b === doc ? 1 : 1389 aup ? -1 : 1390 bup ? 1 : 1391 sortInput ? 1392 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 1393 0; 1394 1395 // If the nodes are siblings, we can do a quick check 1396 } else if ( aup === bup ) { 1397 return siblingCheck( a, b ); 1398 } 1399 1400 // Otherwise we need full lists of their ancestors for comparison 1401 cur = a; 1402 while ( (cur = cur.parentNode) ) { 1403 ap.unshift( cur ); 1404 } 1405 cur = b; 1406 while ( (cur = cur.parentNode) ) { 1407 bp.unshift( cur ); 1408 } 1409 1410 // Walk down the tree looking for a discrepancy 1411 while ( ap[i] === bp[i] ) { 1412 i++; 1413 } 1414 1415 return i ? 1416 // Do a sibling check if the nodes have a common ancestor 1417 siblingCheck( ap[i], bp[i] ) : 1418 1419 // Otherwise nodes in our document sort first 1420 ap[i] === preferredDoc ? -1 : 1421 bp[i] === preferredDoc ? 1 : 1422 0; 1423 }; 1424 1425 return doc; 1426}; 1427 1428Sizzle.matches = function( expr, elements ) { 1429 return Sizzle( expr, null, null, elements ); 1430}; 1431 1432Sizzle.matchesSelector = function( elem, expr ) { 1433 // Set document vars if needed 1434 if ( ( elem.ownerDocument || elem ) !== document ) { 1435 setDocument( elem ); 1436 } 1437 1438 // Make sure that attribute selectors are quoted 1439 expr = expr.replace( rattributeQuotes, "='$1']" ); 1440 1441 if ( support.matchesSelector && documentIsHTML && 1442 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && 1443 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { 1444 1445 try { 1446 var ret = matches.call( elem, expr ); 1447 1448 // IE 9's matchesSelector returns false on disconnected nodes 1449 if ( ret || support.disconnectedMatch || 1450 // As well, disconnected nodes are said to be in a document 1451 // fragment in IE 9 1452 elem.document && elem.document.nodeType !== 11 ) { 1453 return ret; 1454 } 1455 } catch (e) {} 1456 } 1457 1458 return Sizzle( expr, document, null, [ elem ] ).length > 0; 1459}; 1460 1461Sizzle.contains = function( context, elem ) { 1462 // Set document vars if needed 1463 if ( ( context.ownerDocument || context ) !== document ) { 1464 setDocument( context ); 1465 } 1466 return contains( context, elem ); 1467}; 1468 1469Sizzle.attr = function( elem, name ) { 1470 // Set document vars if needed 1471 if ( ( elem.ownerDocument || elem ) !== document ) { 1472 setDocument( elem ); 1473 } 1474 1475 var fn = Expr.attrHandle[ name.toLowerCase() ], 1476 // Don't get fooled by Object.prototype properties (jQuery #13807) 1477 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? 1478 fn( elem, name, !documentIsHTML ) : 1479 undefined; 1480 1481 return val !== undefined ? 1482 val : 1483 support.attributes || !documentIsHTML ? 1484 elem.getAttribute( name ) : 1485 (val = elem.getAttributeNode(name)) && val.specified ? 1486 val.value : 1487 null; 1488}; 1489 1490Sizzle.error = function( msg ) { 1491 throw new Error( "Syntax error, unrecognized expression: " + msg ); 1492}; 1493 1494/** 1495 * Document sorting and removing duplicates 1496 * @param {ArrayLike} results 1497 */ 1498Sizzle.uniqueSort = function( results ) { 1499 var elem, 1500 duplicates = [], 1501 j = 0, 1502 i = 0; 1503 1504 // Unless we *know* we can detect duplicates, assume their presence 1505 hasDuplicate = !support.detectDuplicates; 1506 sortInput = !support.sortStable && results.slice( 0 ); 1507 results.sort( sortOrder ); 1508 1509 if ( hasDuplicate ) { 1510 while ( (elem = results[i++]) ) { 1511 if ( elem === results[ i ] ) { 1512 j = duplicates.push( i ); 1513 } 1514 } 1515 while ( j-- ) { 1516 results.splice( duplicates[ j ], 1 ); 1517 } 1518 } 1519 1520 // Clear input after sorting to release objects 1521 // See https://github.com/jquery/sizzle/pull/225 1522 sortInput = null; 1523 1524 return results; 1525}; 1526 1527/** 1528 * Utility function for retrieving the text value of an array of DOM nodes 1529 * @param {Array|Element} elem 1530 */ 1531getText = Sizzle.getText = function( elem ) { 1532 var node, 1533 ret = "", 1534 i = 0, 1535 nodeType = elem.nodeType; 1536 1537 if ( !nodeType ) { 1538 // If no nodeType, this is expected to be an array 1539 while ( (node = elem[i++]) ) {
vendor: 4,161 bytes, lines 1540-1692
1540 // Do not traverse comment nodes 1541 ret += getText( node ); 1542 } 1543 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { 1544 // Use textContent for elements 1545 // innerText usage removed for consistency of new lines (jQuery #11153) 1546 if ( typeof elem.textContent === "string" ) { 1547 return elem.textContent; 1548 } else { 1549 // Traverse its children 1550 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 1551 ret += getText( elem ); 1552 } 1553 } 1554 } else if ( nodeType === 3 || nodeType === 4 ) { 1555 return elem.nodeValue; 1556 } 1557 // Do not include comment or processing instruction nodes 1558 1559 return ret; 1560}; 1561 1562Expr = Sizzle.selectors = { 1563 1564 // Can be adjusted by the user 1565 cacheLength: 50, 1566 1567 createPseudo: markFunction, 1568 1569 match: matchExpr, 1570 1571 attrHandle: {}, 1572 1573 find: {}, 1574 1575 relative: { 1576 ">": { dir: "parentNode", first: true }, 1577 " ": { dir: "parentNode" }, 1578 "+": { dir: "previousSibling", first: true }, 1579 "~": { dir: "previousSibling" } 1580 }, 1581 1582 preFilter: { 1583 "ATTR": function( match ) { 1584 match[1] = match[1].replace( runescape, funescape ); 1585 1586 // Move the given value to match[3] whether quoted or unquoted 1587 match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); 1588 1589 if ( match[2] === "~=" ) { 1590 match[3] = " " + match[3] + " "; 1591 } 1592 1593 return match.slice( 0, 4 ); 1594 }, 1595 1596 "CHILD": function( match ) { 1597 /* matches from matchExpr["CHILD"] 1598 1 type (only|nth|...) 1599 2 what (child|of-type) 1600 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 1601 4 xn-component of xn+y argument ([+-]?\d*n|) 1602 5 sign of xn-component 1603 6 x of xn-component 1604 7 sign of y-component 1605 8 y of y-component 1606 */ 1607 match[1] = match[1].toLowerCase(); 1608 1609 if ( match[1].slice( 0, 3 ) === "nth" ) { 1610 // nth-* requires argument 1611 if ( !match[3] ) { 1612 Sizzle.error( match[0] ); 1613 } 1614 1615 // numeric x and y parameters for Expr.filter.CHILD 1616 // remember that false/true cast respectively to 0/1 1617 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); 1618 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); 1619 1620 // other types prohibit arguments 1621 } else if ( match[3] ) { 1622 Sizzle.error( match[0] ); 1623 } 1624 1625 return match; 1626 }, 1627 1628 "PSEUDO": function( match ) { 1629 var excess, 1630 unquoted = !match[6] && match[2]; 1631 1632 if ( matchExpr["CHILD"].test( match[0] ) ) { 1633 return null; 1634 } 1635 1636 // Accept quoted arguments as-is 1637 if ( match[3] ) { 1638 match[2] = match[4] || match[5] || ""; 1639 1640 // Strip excess characters from unquoted arguments 1641 } else if ( unquoted && rpseudo.test( unquoted ) && 1642 // Get excess from tokenize (recursively) 1643 (excess = tokenize( unquoted, true )) && 1644 // advance to the next closing parenthesis 1645 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { 1646 1647 // excess is a negative index 1648 match[0] = match[0].slice( 0, excess ); 1649 match[2] = unquoted.slice( 0, excess ); 1650 } 1651 1652 // Return only captures needed by the pseudo filter method (type and argument) 1653 return match.slice( 0, 3 ); 1654 } 1655 }, 1656 1657 filter: { 1658 1659 "TAG": function( nodeNameSelector ) { 1660 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); 1661 return nodeNameSelector === "*" ? 1662 function() { return true; } : 1663 function( elem ) { 1664 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; 1665 }; 1666 }, 1667 1668 "CLASS": function( className ) { 1669 var pattern = classCache[ className + " " ]; 1670 1671 return pattern || 1672 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && 1673 classCache( className, function( elem ) { 1674 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); 1675 }); 1676 }, 1677 1678 "ATTR": function( name, operator, check ) { 1679 return function( elem ) { 1680 var result = Sizzle.attr( elem, name ); 1681 1682 if ( result == null ) { 1683 return operator === "!="; 1684 } 1685 if ( !operator ) { 1686 return true; 1687 } 1688 1689 result += ""; 1690 1691 return operator === "=" ? result === check : 1692 operator === "!=" ? result !== check :
vendor: 6,854 bytes, lines 1693-1898
1693 operator === "^=" ? check && result.indexOf( check ) === 0 : 1694 operator === "*=" ? check && result.indexOf( check ) > -1 : 1695 operator === "$=" ? check && result.slice( -check.length ) === check : 1696 operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : 1697 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : 1698 false; 1699 }; 1700 }, 1701 1702 "CHILD": function( type, what, argument, first, last ) { 1703 var simple = type.slice( 0, 3 ) !== "nth", 1704 forward = type.slice( -4 ) !== "last", 1705 ofType = what === "of-type"; 1706 1707 return first === 1 && last === 0 ? 1708 1709 // Shortcut for :nth-*(n) 1710 function( elem ) { 1711 return !!elem.parentNode; 1712 } : 1713 1714 function( elem, context, xml ) { 1715 var cache, outerCache, node, diff, nodeIndex, start, 1716 dir = simple !== forward ? "nextSibling" : "previousSibling", 1717 parent = elem.parentNode, 1718 name = ofType && elem.nodeName.toLowerCase(), 1719 useCache = !xml && !ofType; 1720 1721 if ( parent ) { 1722 1723 // :(first|last|only)-(child|of-type) 1724 if ( simple ) { 1725 while ( dir ) { 1726 node = elem; 1727 while ( (node = node[ dir ]) ) { 1728 if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { 1729 return false; 1730 } 1731 } 1732 // Reverse direction for :only-* (if we haven't yet done so) 1733 start = dir = type === "only" && !start && "nextSibling"; 1734 } 1735 return true; 1736 } 1737 1738 start = [ forward ? parent.firstChild : parent.lastChild ]; 1739 1740 // non-xml :nth-child(...) stores cache data on `parent` 1741 if ( forward && useCache ) { 1742 // Seek `elem` from a previously-cached index 1743 outerCache = parent[ expando ] || (parent[ expando ] = {}); 1744 cache = outerCache[ type ] || []; 1745 nodeIndex = cache[0] === dirruns && cache[1]; 1746 diff = cache[0] === dirruns && cache[2]; 1747 node = nodeIndex && parent.childNodes[ nodeIndex ]; 1748 1749 while ( (node = ++nodeIndex && node && node[ dir ] || 1750 1751 // Fallback to seeking `elem` from the start 1752 (diff = nodeIndex = 0) || start.pop()) ) { 1753 1754 // When found, cache indexes on `parent` and break 1755 if ( node.nodeType === 1 && ++diff && node === elem ) { 1756 outerCache[ type ] = [ dirruns, nodeIndex, diff ]; 1757 break; 1758 } 1759 } 1760 1761 // Use previously-cached element index if available 1762 } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { 1763 diff = cache[1]; 1764 1765 // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) 1766 } else { 1767 // Use the same loop as above to seek `elem` from the start 1768 while ( (node = ++nodeIndex && node && node[ dir ] || 1769 (diff = nodeIndex = 0) || start.pop()) ) { 1770 1771 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { 1772 // Cache the index of each encountered element 1773 if ( useCache ) { 1774 (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; 1775 } 1776 1777 if ( node === elem ) { 1778 break; 1779 } 1780 } 1781 } 1782 } 1783 1784 // Incorporate the offset, then check against cycle size 1785 diff -= last; 1786 return diff === first || ( diff % first === 0 && diff / first >= 0 ); 1787 } 1788 }; 1789 }, 1790 1791 "PSEUDO": function( pseudo, argument ) { 1792 // pseudo-class names are case-insensitive 1793 // http://www.w3.org/TR/selectors/#pseudo-classes 1794 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters 1795 // Remember that setFilters inherits from pseudos 1796 var args, 1797 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || 1798 Sizzle.error( "unsupported pseudo: " + pseudo ); 1799 1800 // The user may use createPseudo to indicate that 1801 // arguments are needed to create the filter function 1802 // just as Sizzle does 1803 if ( fn[ expando ] ) { 1804 return fn( argument ); 1805 } 1806 1807 // But maintain support for old signatures 1808 if ( fn.length > 1 ) { 1809 args = [ pseudo, pseudo, "", argument ]; 1810 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? 1811 markFunction(function( seed, matches ) { 1812 var idx, 1813 matched = fn( seed, argument ), 1814 i = matched.length; 1815 while ( i-- ) { 1816 idx = indexOf( seed, matched[i] ); 1817 seed[ idx ] = !( matches[ idx ] = matched[i] ); 1818 } 1819 }) : 1820 function( elem ) { 1821 return fn( elem, 0, args ); 1822 }; 1823 } 1824 1825 return fn; 1826 } 1827 }, 1828 1829 pseudos: { 1830 // Potentially complex pseudos 1831 "not": markFunction(function( selector ) { 1832 // Trim the selector passed to compile 1833 // to avoid treating leading and trailing 1834 // spaces as combinators 1835 var input = [], 1836 results = [], 1837 matcher = compile( selector.replace( rtrim, "$1" ) ); 1838 1839 return matcher[ expando ] ? 1840 markFunction(function( seed, matches, context, xml ) { 1841 var elem, 1842 unmatched = matcher( seed, null, xml, [] ), 1843 i = seed.length; 1844 1845 // Match elements unmatched by `matcher` 1846 while ( i-- ) { 1847 if ( (elem = unmatched[i]) ) { 1848 seed[i] = !(matches[i] = elem); 1849 } 1850 } 1851 }) : 1852 function( elem, context, xml ) { 1853 input[0] = elem; 1854 matcher( input, null, xml, results ); 1855 // Don't keep the element (issue #299) 1856 input[0] = null; 1857 return !results.pop(); 1858 }; 1859 }), 1860 1861 "has": markFunction(function( selector ) { 1862 return function( elem ) { 1863 return Sizzle( selector, elem ).length > 0; 1864 }; 1865 }), 1866 1867 "contains": markFunction(function( text ) { 1868 text = text.replace( runescape, funescape ); 1869 return function( elem ) { 1870 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; 1871 }; 1872 }), 1873 1874 // "Whether an element is represented by a :lang() selector 1875 // is based solely on the element's language value 1876 // being equal to the identifier C, 1877 // or beginning with the identifier C immediately followed by "-". 1878 // The matching of C against the element's language value is performed case-insensitively. 1879 // The identifier C does not have to be a valid language name." 1880 // http://www.w3.org/TR/selectors/#lang-pseudo 1881 "lang": markFunction( function( lang ) { 1882 // lang value must be a valid identifier 1883 if ( !ridentifier.test(lang || "") ) { 1884 Sizzle.error( "unsupported lang: " + lang ); 1885 } 1886 lang = lang.replace( runescape, funescape ).toLowerCase(); 1887 return function( elem ) { 1888 var elemLang; 1889 do { 1890 if ( (elemLang = documentIsHTML ? 1891 elem.lang : 1892 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { 1893 1894 elemLang = elemLang.toLowerCase(); 1895 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; 1896 } 1897 } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); 1898 return false;
vendor: 4,543 bytes, lines 1899-2070
1899 }; 1900 }), 1901 1902 // Miscellaneous 1903 "target": function( elem ) { 1904 var hash = window.location && window.location.hash; 1905 return hash && hash.slice( 1 ) === elem.id; 1906 }, 1907 1908 "root": function( elem ) { 1909 return elem === docElem; 1910 }, 1911 1912 "focus": function( elem ) { 1913 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); 1914 }, 1915 1916 // Boolean properties 1917 "enabled": function( elem ) { 1918 return elem.disabled === false; 1919 }, 1920 1921 "disabled": function( elem ) { 1922 return elem.disabled === true; 1923 }, 1924 1925 "checked": function( elem ) { 1926 // In CSS3, :checked should return both checked and selected elements 1927 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 1928 var nodeName = elem.nodeName.toLowerCase(); 1929 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); 1930 }, 1931 1932 "selected": function( elem ) { 1933 // Accessing this property makes selected-by-default 1934 // options in Safari work properly 1935 if ( elem.parentNode ) { 1936 elem.parentNode.selectedIndex; 1937 } 1938 1939 return elem.selected === true; 1940 }, 1941 1942 // Contents 1943 "empty": function( elem ) { 1944 // http://www.w3.org/TR/selectors/#empty-pseudo 1945 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), 1946 // but not by others (comment: 8; processing instruction: 7; etc.) 1947 // nodeType < 6 works because attributes (2) do not appear as children 1948 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 1949 if ( elem.nodeType < 6 ) { 1950 return false; 1951 } 1952 } 1953 return true; 1954 }, 1955 1956 "parent": function( elem ) { 1957 return !Expr.pseudos["empty"]( elem ); 1958 }, 1959 1960 // Element/input types 1961 "header": function( elem ) { 1962 return rheader.test( elem.nodeName ); 1963 }, 1964 1965 "input": function( elem ) { 1966 return rinputs.test( elem.nodeName ); 1967 }, 1968 1969 "button": function( elem ) { 1970 var name = elem.nodeName.toLowerCase(); 1971 return name === "input" && elem.type === "button" || name === "button"; 1972 }, 1973 1974 "text": function( elem ) { 1975 var attr; 1976 return elem.nodeName.toLowerCase() === "input" && 1977 elem.type === "text" && 1978 1979 // Support: IE<8 1980 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" 1981 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); 1982 }, 1983 1984 // Position-in-collection 1985 "first": createPositionalPseudo(function() { 1986 return [ 0 ]; 1987 }), 1988 1989 "last": createPositionalPseudo(function( matchIndexes, length ) { 1990 return [ length - 1 ]; 1991 }), 1992 1993 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { 1994 return [ argument < 0 ? argument + length : argument ]; 1995 }), 1996 1997 "even": createPositionalPseudo(function( matchIndexes, length ) { 1998 var i = 0; 1999 for ( ; i < length; i += 2 ) { 2000 matchIndexes.push( i ); 2001 } 2002 return matchIndexes; 2003 }), 2004 2005 "odd": createPositionalPseudo(function( matchIndexes, length ) { 2006 var i = 1; 2007 for ( ; i < length; i += 2 ) { 2008 matchIndexes.push( i ); 2009 } 2010 return matchIndexes; 2011 }), 2012 2013 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { 2014 var i = argument < 0 ? argument + length : argument; 2015 for ( ; --i >= 0; ) { 2016 matchIndexes.push( i ); 2017 } 2018 return matchIndexes; 2019 }), 2020 2021 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { 2022 var i = argument < 0 ? argument + length : argument; 2023 for ( ; ++i < length; ) { 2024 matchIndexes.push( i ); 2025 } 2026 return matchIndexes; 2027 }) 2028 } 2029}; 2030 2031Expr.pseudos["nth"] = Expr.pseudos["eq"]; 2032 2033// Add button/input type pseudos 2034for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { 2035 Expr.pseudos[ i ] = createInputPseudo( i ); 2036} 2037for ( i in { submit: true, reset: true } ) { 2038 Expr.pseudos[ i ] = createButtonPseudo( i ); 2039} 2040 2041// Easy API for creating new setFilters 2042function setFilters() {} 2043setFilters.prototype = Expr.filters = Expr.pseudos; 2044Expr.setFilters = new setFilters(); 2045 2046tokenize = Sizzle.tokenize = function( selector, parseOnly ) { 2047 var matched, match, tokens, type, 2048 soFar, groups, preFilters, 2049 cached = tokenCache[ selector + " " ]; 2050 2051 if ( cached ) { 2052 return parseOnly ? 0 : cached.slice( 0 ); 2053 } 2054 2055 soFar = selector; 2056 groups = []; 2057 preFilters = Expr.preFilter; 2058 2059 while ( soFar ) { 2060 2061 // Comma and first run 2062 if ( !matched || (match = rcomma.exec( soFar )) ) { 2063 if ( match ) { 2064 // Don't consume trailing commas as valid 2065 soFar = soFar.slice( match[0].length ) || soFar; 2066 } 2067 groups.push( (tokens = []) ); 2068 } 2069 2070 matched = false;
vendor: 17,197 bytes, lines 2071-2692
2071 2072 // Combinators 2073 if ( (match = rcombinators.exec( soFar )) ) { 2074 matched = match.shift(); 2075 tokens.push({ 2076 value: matched, 2077 // Cast descendant combinators to space 2078 type: match[0].replace( rtrim, " " ) 2079 }); 2080 soFar = soFar.slice( matched.length ); 2081 } 2082 2083 // Filters 2084 for ( type in Expr.filter ) { 2085 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || 2086 (match = preFilters[ type ]( match ))) ) { 2087 matched = match.shift(); 2088 tokens.push({ 2089 value: matched, 2090 type: type, 2091 matches: match 2092 }); 2093 soFar = soFar.slice( matched.length ); 2094 } 2095 } 2096 2097 if ( !matched ) { 2098 break; 2099 } 2100 } 2101 2102 // Return the length of the invalid excess 2103 // if we're just parsing 2104 // Otherwise, throw an error or return tokens 2105 return parseOnly ? 2106 soFar.length : 2107 soFar ? 2108 Sizzle.error( selector ) : 2109 // Cache the tokens 2110 tokenCache( selector, groups ).slice( 0 ); 2111}; 2112 2113function toSelector( tokens ) { 2114 var i = 0, 2115 len = tokens.length, 2116 selector = ""; 2117 for ( ; i < len; i++ ) { 2118 selector += tokens[i].value; 2119 } 2120 return selector; 2121} 2122 2123function addCombinator( matcher, combinator, base ) { 2124 var dir = combinator.dir, 2125 checkNonElements = base && dir === "parentNode", 2126 doneName = done++; 2127 2128 return combinator.first ? 2129 // Check against closest ancestor/preceding element 2130 function( elem, context, xml ) { 2131 while ( (elem = elem[ dir ]) ) { 2132 if ( elem.nodeType === 1 || checkNonElements ) { 2133 return matcher( elem, context, xml ); 2134 } 2135 } 2136 } : 2137 2138 // Check against all ancestor/preceding elements 2139 function( elem, context, xml ) { 2140 var oldCache, outerCache, 2141 newCache = [ dirruns, doneName ]; 2142 2143 // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching 2144 if ( xml ) { 2145 while ( (elem = elem[ dir ]) ) { 2146 if ( elem.nodeType === 1 || checkNonElements ) { 2147 if ( matcher( elem, context, xml ) ) { 2148 return true; 2149 } 2150 } 2151 } 2152 } else { 2153 while ( (elem = elem[ dir ]) ) { 2154 if ( elem.nodeType === 1 || checkNonElements ) { 2155 outerCache = elem[ expando ] || (elem[ expando ] = {}); 2156 if ( (oldCache = outerCache[ dir ]) && 2157 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { 2158 2159 // Assign to newCache so results back-propagate to previous elements 2160 return (newCache[ 2 ] = oldCache[ 2 ]); 2161 } else { 2162 // Reuse newcache so results back-propagate to previous elements 2163 outerCache[ dir ] = newCache; 2164 2165 // A match means we're done; a fail means we have to keep checking 2166 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { 2167 return true; 2168 } 2169 } 2170 } 2171 } 2172 } 2173 }; 2174} 2175 2176function elementMatcher( matchers ) { 2177 return matchers.length > 1 ? 2178 function( elem, context, xml ) { 2179 var i = matchers.length; 2180 while ( i-- ) { 2181 if ( !matchers[i]( elem, context, xml ) ) { 2182 return false; 2183 } 2184 } 2185 return true; 2186 } : 2187 matchers[0]; 2188} 2189 2190function multipleContexts( selector, contexts, results ) { 2191 var i = 0, 2192 len = contexts.length; 2193 for ( ; i < len; i++ ) { 2194 Sizzle( selector, contexts[i], results ); 2195 } 2196 return results; 2197} 2198 2199function condense( unmatched, map, filter, context, xml ) { 2200 var elem, 2201 newUnmatched = [], 2202 i = 0, 2203 len = unmatched.length, 2204 mapped = map != null; 2205 2206 for ( ; i < len; i++ ) { 2207 if ( (elem = unmatched[i]) ) { 2208 if ( !filter || filter( elem, context, xml ) ) { 2209 newUnmatched.push( elem ); 2210 if ( mapped ) { 2211 map.push( i ); 2212 } 2213 } 2214 } 2215 } 2216 2217 return newUnmatched; 2218} 2219 2220function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { 2221 if ( postFilter && !postFilter[ expando ] ) { 2222 postFilter = setMatcher( postFilter ); 2223 } 2224 if ( postFinder && !postFinder[ expando ] ) { 2225 postFinder = setMatcher( postFinder, postSelector ); 2226 } 2227 return markFunction(function( seed, results, context, xml ) { 2228 var temp, i, elem, 2229 preMap = [], 2230 postMap = [], 2231 preexisting = results.length, 2232 2233 // Get initial elements from seed or context 2234 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), 2235 2236 // Prefilter to get matcher input, preserving a map for seed-results synchronization 2237 matcherIn = preFilter && ( seed || !selector ) ? 2238 condense( elems, preMap, preFilter, context, xml ) : 2239 elems, 2240 2241 matcherOut = matcher ? 2242 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, 2243 postFinder || ( seed ? preFilter : preexisting || postFilter ) ? 2244 2245 // ...intermediate processing is necessary 2246 [] : 2247 2248 // ...otherwise use results directly 2249 results : 2250 matcherIn; 2251 2252 // Find primary matches 2253 if ( matcher ) { 2254 matcher( matcherIn, matcherOut, context, xml ); 2255 } 2256 2257 // Apply postFilter 2258 if ( postFilter ) { 2259 temp = condense( matcherOut, postMap ); 2260 postFilter( temp, [], context, xml ); 2261 2262 // Un-match failing elements by moving them back to matcherIn 2263 i = temp.length; 2264 while ( i-- ) { 2265 if ( (elem = temp[i]) ) { 2266 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); 2267 } 2268 } 2269 } 2270 2271 if ( seed ) { 2272 if ( postFinder || preFilter ) { 2273 if ( postFinder ) { 2274 // Get the final matcherOut by condensing this intermediate into postFinder contexts 2275 temp = []; 2276 i = matcherOut.length; 2277 while ( i-- ) { 2278 if ( (elem = matcherOut[i]) ) { 2279 // Restore matcherIn since elem is not yet a final match 2280 temp.push( (matcherIn[i] = elem) ); 2281 } 2282 } 2283 postFinder( null, (matcherOut = []), temp, xml ); 2284 } 2285 2286 // Move matched elements from seed to results to keep them synchronized 2287 i = matcherOut.length; 2288 while ( i-- ) { 2289 if ( (elem = matcherOut[i]) && 2290 (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { 2291 2292 seed[temp] = !(results[temp] = elem); 2293 } 2294 } 2295 } 2296 2297 // Add elements to results, through postFinder if defined 2298 } else { 2299 matcherOut = condense( 2300 matcherOut === results ? 2301 matcherOut.splice( preexisting, matcherOut.length ) : 2302 matcherOut 2303 ); 2304 if ( postFinder ) { 2305 postFinder( null, results, matcherOut, xml ); 2306 } else { 2307 push.apply( results, matcherOut ); 2308 } 2309 } 2310 }); 2311} 2312 2313function matcherFromTokens( tokens ) { 2314 var checkContext, matcher, j, 2315 len = tokens.length, 2316 leadingRelative = Expr.relative[ tokens[0].type ], 2317 implicitRelative = leadingRelative || Expr.relative[" "], 2318 i = leadingRelative ? 1 : 0, 2319 2320 // The foundational matcher ensures that elements are reachable from top-level context(s) 2321 matchContext = addCombinator( function( elem ) { 2322 return elem === checkContext; 2323 }, implicitRelative, true ), 2324 matchAnyContext = addCombinator( function( elem ) { 2325 return indexOf( checkContext, elem ) > -1; 2326 }, implicitRelative, true ), 2327 matchers = [ function( elem, context, xml ) { 2328 var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( 2329 (checkContext = context).nodeType ? 2330 matchContext( elem, context, xml ) : 2331 matchAnyContext( elem, context, xml ) ); 2332 // Avoid hanging onto element (issue #299) 2333 checkContext = null; 2334 return ret; 2335 } ]; 2336 2337 for ( ; i < len; i++ ) { 2338 if ( (matcher = Expr.relative[ tokens[i].type ]) ) { 2339 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; 2340 } else { 2341 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); 2342 2343 // Return special upon seeing a positional matcher 2344 if ( matcher[ expando ] ) { 2345 // Find the next relative operator (if any) for proper handling 2346 j = ++i; 2347 for ( ; j < len; j++ ) { 2348 if ( Expr.relative[ tokens[j].type ] ) { 2349 break; 2350 } 2351 } 2352 return setMatcher( 2353 i > 1 && elementMatcher( matchers ), 2354 i > 1 && toSelector( 2355 // If the preceding token was a descendant combinator, insert an implicit any-element `*` 2356 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) 2357 ).replace( rtrim, "$1" ), 2358 matcher, 2359 i < j && matcherFromTokens( tokens.slice( i, j ) ), 2360 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), 2361 j < len && toSelector( tokens ) 2362 ); 2363 } 2364 matchers.push( matcher ); 2365 } 2366 } 2367 2368 return elementMatcher( matchers ); 2369} 2370 2371function matcherFromGroupMatchers( elementMatchers, setMatchers ) { 2372 var bySet = setMatchers.length > 0, 2373 byElement = elementMatchers.length > 0, 2374 superMatcher = function( seed, context, xml, results, outermost ) { 2375 var elem, j, matcher, 2376 matchedCount = 0, 2377 i = "0", 2378 unmatched = seed && [], 2379 setMatched = [], 2380 contextBackup = outermostContext, 2381 // We must always have either seed elements or outermost context 2382 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), 2383 // Use integer dirruns iff this is the outermost matcher 2384 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), 2385 len = elems.length; 2386 2387 if ( outermost ) { 2388 outermostContext = context !== document && context; 2389 } 2390 2391 // Add elements passing elementMatchers directly to results 2392 // Keep `i` a string if there are no elements so `matchedCount` will be "00" below 2393 // Support: IE<9, Safari 2394 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id 2395 for ( ; i !== len && (elem = elems[i]) != null; i++ ) { 2396 if ( byElement && elem ) { 2397 j = 0; 2398 while ( (matcher = elementMatchers[j++]) ) { 2399 if ( matcher( elem, context, xml ) ) { 2400 results.push( elem ); 2401 break; 2402 } 2403 } 2404 if ( outermost ) { 2405 dirruns = dirrunsUnique; 2406 } 2407 } 2408 2409 // Track unmatched elements for set filters 2410 if ( bySet ) { 2411 // They will have gone through all possible matchers 2412 if ( (elem = !matcher && elem) ) { 2413 matchedCount--; 2414 } 2415 2416 // Lengthen the array for every element, matched or not 2417 if ( seed ) { 2418 unmatched.push( elem ); 2419 } 2420 } 2421 } 2422 2423 // Apply set filters to unmatched elements 2424 matchedCount += i; 2425 if ( bySet && i !== matchedCount ) { 2426 j = 0; 2427 while ( (matcher = setMatchers[j++]) ) { 2428 matcher( unmatched, setMatched, context, xml ); 2429 } 2430 2431 if ( seed ) { 2432 // Reintegrate element matches to eliminate the need for sorting 2433 if ( matchedCount > 0 ) { 2434 while ( i-- ) { 2435 if ( !(unmatched[i] || setMatched[i]) ) { 2436 setMatched[i] = pop.call( results ); 2437 } 2438 } 2439 } 2440 2441 // Discard index placeholder values to get only actual matches 2442 setMatched = condense( setMatched ); 2443 } 2444 2445 // Add matches to results 2446 push.apply( results, setMatched ); 2447 2448 // Seedless set matches succeeding multiple successful matchers stipulate sorting 2449 if ( outermost && !seed && setMatched.length > 0 && 2450 ( matchedCount + setMatchers.length ) > 1 ) { 2451 2452 Sizzle.uniqueSort( results ); 2453 } 2454 } 2455 2456 // Override manipulation of globals by nested matchers 2457 if ( outermost ) { 2458 dirruns = dirrunsUnique; 2459 outermostContext = contextBackup; 2460 } 2461 2462 return unmatched; 2463 }; 2464 2465 return bySet ? 2466 markFunction( superMatcher ) : 2467 superMatcher; 2468} 2469 2470compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { 2471 var i, 2472 setMatchers = [], 2473 elementMatchers = [], 2474 cached = compilerCache[ selector + " " ]; 2475 2476 if ( !cached ) { 2477 // Generate a function of recursive functions that can be used to check each element 2478 if ( !match ) { 2479 match = tokenize( selector ); 2480 } 2481 i = match.length; 2482 while ( i-- ) { 2483 cached = matcherFromTokens( match[i] ); 2484 if ( cached[ expando ] ) { 2485 setMatchers.push( cached ); 2486 } else { 2487 elementMatchers.push( cached ); 2488 } 2489 } 2490 2491 // Cache the compiled function 2492 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); 2493 2494 // Save selector and tokenization 2495 cached.selector = selector; 2496 } 2497 return cached; 2498}; 2499 2500/** 2501 * A low-level selection function that works with Sizzle's compiled 2502 * selector functions 2503 * @param {String|Function} selector A selector or a pre-compiled 2504 * selector function built with Sizzle.compile 2505 * @param {Element} context 2506 * @param {Array} [results] 2507 * @param {Array} [seed] A set of elements to match against 2508 */ 2509select = Sizzle.select = function( selector, context, results, seed ) { 2510 var i, tokens, token, type, find, 2511 compiled = typeof selector === "function" && selector, 2512 match = !seed && tokenize( (selector = compiled.selector || selector) ); 2513 2514 results = results || []; 2515 2516 // Try to minimize operations if there is no seed and only one group 2517 if ( match.length === 1 ) { 2518 2519 // Take a shortcut and set the context if the root selector is an ID 2520 tokens = match[0] = match[0].slice( 0 ); 2521 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && 2522 support.getById && context.nodeType === 9 && documentIsHTML && 2523 Expr.relative[ tokens[1].type ] ) { 2524 2525 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; 2526 if ( !context ) { 2527 return results; 2528 2529 // Precompiled matchers will still verify ancestry, so step up a level 2530 } else if ( compiled ) { 2531 context = context.parentNode; 2532 } 2533 2534 selector = selector.slice( tokens.shift().value.length ); 2535 } 2536 2537 // Fetch a seed set for right-to-left matching 2538 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; 2539 while ( i-- ) { 2540 token = tokens[i]; 2541 2542 // Abort if we hit a combinator 2543 if ( Expr.relative[ (type = token.type) ] ) { 2544 break; 2545 } 2546 if ( (find = Expr.find[ type ]) ) { 2547 // Search, expanding context for leading sibling combinators 2548 if ( (seed = find( 2549 token.matches[0].replace( runescape, funescape ), 2550 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context 2551 )) ) { 2552 2553 // If seed is empty or no tokens remain, we can return early 2554 tokens.splice( i, 1 ); 2555 selector = seed.length && toSelector( tokens ); 2556 if ( !selector ) { 2557 push.apply( results, seed ); 2558 return results; 2559 } 2560 2561 break; 2562 } 2563 } 2564 } 2565 } 2566 2567 // Compile and execute a filtering function if one is not provided 2568 // Provide `match` to avoid retokenization if we modified the selector above 2569 ( compiled || compile( selector, match ) )( 2570 seed, 2571 context, 2572 !documentIsHTML, 2573 results, 2574 rsibling.test( selector ) && testContext( context.parentNode ) || context 2575 ); 2576 return results; 2577}; 2578 2579// One-time assignments 2580 2581// Sort stability 2582support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; 2583 2584// Support: Chrome 14-35+ 2585// Always assume duplicates if they aren't passed to the comparison function 2586support.detectDuplicates = !!hasDuplicate; 2587 2588// Initialize against the default document 2589setDocument(); 2590 2591// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) 2592// Detached nodes confoundingly follow *each other* 2593support.sortDetached = assert(function( div1 ) { 2594 // Should return 1, but returns 4 (following) 2595 return div1.compareDocumentPosition( document.createElement("div") ) & 1; 2596}); 2597 2598// Support: IE<8 2599// Prevent attribute/property "interpolation" 2600// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx 2601if ( !assert(function( div ) { 2602 div.innerHTML = "<a href='#'></a>"; 2603 return div.firstChild.getAttribute("href") === "#" ; 2604}) ) { 2605 addHandle( "type|href|height|width", function( elem, name, isXML ) { 2606 if ( !isXML ) { 2607 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); 2608 } 2609 }); 2610} 2611 2612// Support: IE<9 2613// Use defaultValue in place of getAttribute("value") 2614if ( !support.attributes || !assert(function( div ) { 2615 div.innerHTML = "<input/>"; 2616 div.firstChild.setAttribute( "value", "" ); 2617 return div.firstChild.getAttribute( "value" ) === ""; 2618}) ) { 2619 addHandle( "value", function( elem, name, isXML ) { 2620 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { 2621 return elem.defaultValue; 2622 } 2623 }); 2624} 2625 2626// Support: IE<9 2627// Use getAttributeNode to fetch booleans when getAttribute lies 2628if ( !assert(function( div ) { 2629 return div.getAttribute("disabled") == null; 2630}) ) { 2631 addHandle( booleans, function( elem, name, isXML ) { 2632 var val; 2633 if ( !isXML ) { 2634 return elem[ name ] === true ? name.toLowerCase() : 2635 (val = elem.getAttributeNode( name )) && val.specified ? 2636 val.value : 2637 null; 2638 } 2639 }); 2640} 2641 2642return Sizzle; 2643 2644})( window ); 2645 2646 2647 2648jQuery.find = Sizzle; 2649jQuery.expr = Sizzle.selectors; 2650jQuery.expr[":"] = jQuery.expr.pseudos; 2651jQuery.unique = Sizzle.uniqueSort; 2652jQuery.text = Sizzle.getText; 2653jQuery.isXMLDoc = Sizzle.isXML; 2654jQuery.contains = Sizzle.contains; 2655 2656 2657 2658var rneedsContext = jQuery.expr.match.needsContext; 2659 2660var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); 2661 2662 2663 2664var risSimple = /^.[^:#\[\.,]*$/; 2665 2666// Implement the identical functionality for filter and not 2667function winnow( elements, qualifier, not ) { 2668 if ( jQuery.isFunction( qualifier ) ) { 2669 return jQuery.grep( elements, function( elem, i ) { 2670 /* jshint -W018 */ 2671 return !!qualifier.call( elem, i, elem ) !== not; 2672 }); 2673 2674 } 2675 2676 if ( qualifier.nodeType ) { 2677 return jQuery.grep( elements, function( elem ) { 2678 return ( elem === qualifier ) !== not; 2679 }); 2680 2681 } 2682 2683 if ( typeof qualifier === "string" ) { 2684 if ( risSimple.test( qualifier ) ) { 2685 return jQuery.filter( qualifier, elements, not ); 2686 } 2687 2688 qualifier = jQuery.filter( qualifier, elements ); 2689 } 2690 2691 return jQuery.grep( elements, function( elem ) { 2692 return (
vendor: 94,870 bytes, lines 2692-6142
2692jQuery.inArray( elem, qualifier ) >= 0 ) !== not; 2693 }); 2694} 2695 2696jQuery.filter = function( expr, elems, not ) { 2697 var elem = elems[ 0 ]; 2698 2699 if ( not ) { 2700 expr = ":not(" + expr + ")"; 2701 } 2702 2703 return elems.length === 1 && elem.nodeType === 1 ? 2704 jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : 2705 jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { 2706 return elem.nodeType === 1; 2707 })); 2708}; 2709 2710jQuery.fn.extend({ 2711 find: function( selector ) { 2712 var i, 2713 ret = [], 2714 self = this, 2715 len = self.length; 2716 2717 if ( typeof selector !== "string" ) { 2718 return this.pushStack( jQuery( selector ).filter(function() { 2719 for ( i = 0; i < len; i++ ) { 2720 if ( jQuery.contains( self[ i ], this ) ) { 2721 return true; 2722 } 2723 } 2724 }) ); 2725 } 2726 2727 for ( i = 0; i < len; i++ ) { 2728 jQuery.find( selector, self[ i ], ret ); 2729 } 2730 2731 // Needed because $( selector, context ) becomes $( context ).find( selector ) 2732 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); 2733 ret.selector = this.selector ? this.selector + " " + selector : selector; 2734 return ret; 2735 }, 2736 filter: function( selector ) { 2737 return this.pushStack( winnow(this, selector || [], false) ); 2738 }, 2739 not: function( selector ) { 2740 return this.pushStack( winnow(this, selector || [], true) ); 2741 }, 2742 is: function( selector ) { 2743 return !!winnow( 2744 this, 2745 2746 // If this is a positional/relative selector, check membership in the returned set 2747 // so $("p:first").is("p:last") won't return true for a doc with two "p". 2748 typeof selector === "string" && rneedsContext.test( selector ) ? 2749 jQuery( selector ) : 2750 selector || [], 2751 false 2752 ).length; 2753 } 2754}); 2755 2756 2757// Initialize a jQuery object 2758 2759 2760// A central reference to the root jQuery(document) 2761var rootjQuery, 2762 2763 // Use the correct document accordingly with window argument (sandbox) 2764 document = window.document, 2765 2766 // A simple way to check for HTML strings 2767 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) 2768 // Strict HTML recognition (#11290: must start with <) 2769 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, 2770 2771 init = jQuery.fn.init = function( selector, context ) { 2772 var match, elem; 2773 2774 // HANDLE: $(""), $(null), $(undefined), $(false) 2775 if ( !selector ) { 2776 return this; 2777 } 2778 2779 // Handle HTML strings 2780 if ( typeof selector === "string" ) { 2781 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { 2782 // Assume that strings that start and end with <> are HTML and skip the regex check 2783 match = [ null, selector, null ]; 2784 2785 } else { 2786 match = rquickExpr.exec( selector ); 2787 } 2788 2789 // Match html or make sure no context is specified for #id 2790 if ( match && (match[1] || !context) ) { 2791 2792 // HANDLE: $(html) -> $(array) 2793 if ( match[1] ) { 2794 context = context instanceof jQuery ? context[0] : context; 2795 2796 // scripts is true for back-compat 2797 // Intentionally let the error be thrown if parseHTML is not present 2798 jQuery.merge( this, jQuery.parseHTML( 2799 match[1], 2800 context && context.nodeType ? context.ownerDocument || context : document, 2801 true 2802 ) ); 2803 2804 // HANDLE: $(html, props) 2805 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { 2806 for ( match in context ) { 2807 // Properties of context are called as methods if possible 2808 if ( jQuery.isFunction( this[ match ] ) ) { 2809 this[ match ]( context[ match ] ); 2810 2811 // ...and otherwise set as attributes 2812 } else { 2813 this.attr( match, context[ match ] ); 2814 } 2815 } 2816 } 2817 2818 return this; 2819 2820 // HANDLE: $(#id) 2821 } else { 2822 elem = document.getElementById( match[2] ); 2823 2824 // Check parentNode to catch when Blackberry 4.6 returns 2825 // nodes that are no longer in the document #6963 2826 if ( elem && elem.parentNode ) { 2827 // Handle the case where IE and Opera return items 2828 // by name instead of ID 2829 if ( elem.id !== match[2] ) { 2830 return rootjQuery.find( selector ); 2831 } 2832 2833 // Otherwise, we inject the element directly into the jQuery object 2834 this.length = 1; 2835 this[0] = elem; 2836 } 2837 2838 this.context = document; 2839 this.selector = selector; 2840 return this; 2841 } 2842 2843 // HANDLE: $(expr, $(...)) 2844 } else if ( !context || context.jquery ) { 2845 return ( context || rootjQuery ).find( selector ); 2846 2847 // HANDLE: $(expr, context) 2848 // (which is just equivalent to: $(context).find(expr) 2849 } else { 2850 return this.constructor( context ).find( selector ); 2851 } 2852 2853 // HANDLE: $(DOMElement) 2854 } else if ( selector.nodeType ) { 2855 this.context = this[0] = selector; 2856 this.length = 1; 2857 return this; 2858 2859 // HANDLE: $(function) 2860 // Shortcut for document ready 2861 } else if ( jQuery.isFunction( selector ) ) { 2862 return typeof rootjQuery.ready !== "undefined" ? 2863 rootjQuery.ready( selector ) : 2864 // Execute immediately if ready is not present 2865 selector( jQuery ); 2866 } 2867 2868 if ( selector.selector !== undefined ) { 2869 this.selector = selector.selector; 2870 this.context = selector.context; 2871 } 2872 2873 return jQuery.makeArray( selector, this ); 2874 }; 2875 2876// Give the init function the jQuery prototype for later instantiation 2877init.prototype = jQuery.fn; 2878 2879// Initialize central reference 2880rootjQuery = jQuery( document ); 2881 2882 2883var rparentsprev = /^(?:parents|prev(?:Until|All))/, 2884 // methods guaranteed to produce a unique set when starting from a unique set 2885 guaranteedUnique = { 2886 children: true, 2887 contents: true, 2888 next: true, 2889 prev: true 2890 }; 2891 2892jQuery.extend({ 2893 dir: function( elem, dir, until ) { 2894 var matched = [], 2895 cur = elem[ dir ]; 2896 2897 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { 2898 if ( cur.nodeType === 1 ) { 2899 matched.push( cur ); 2900 } 2901 cur = cur[dir]; 2902 } 2903 return matched; 2904 }, 2905 2906 sibling: function( n, elem ) { 2907 var r = []; 2908 2909 for ( ; n; n = n.nextSibling ) { 2910 if ( n.nodeType === 1 && n !== elem ) { 2911 r.push( n ); 2912 } 2913 } 2914 2915 return r; 2916 } 2917}); 2918 2919jQuery.fn.extend({ 2920 has: function( target ) { 2921 var i, 2922 targets = jQuery( target, this ), 2923 len = targets.length; 2924 2925 return this.filter(function() { 2926 for ( i = 0; i < len; i++ ) { 2927 if ( jQuery.contains( this, targets[i] ) ) { 2928 return true; 2929 } 2930 } 2931 }); 2932 }, 2933 2934 closest: function( selectors, context ) { 2935 var cur, 2936 i = 0, 2937 l = this.length, 2938 matched = [], 2939 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? 2940 jQuery( selectors, context || this.context ) : 2941 0; 2942 2943 for ( ; i < l; i++ ) { 2944 for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { 2945 // Always skip document fragments 2946 if ( cur.nodeType < 11 && (pos ? 2947 pos.index(cur) > -1 : 2948 2949 // Don't pass non-elements to Sizzle 2950 cur.nodeType === 1 && 2951 jQuery.find.matchesSelector(cur, selectors)) ) { 2952 2953 matched.push( cur ); 2954 break; 2955 } 2956 } 2957 } 2958 2959 return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); 2960 }, 2961 2962 // Determine the position of an element within 2963 // the matched set of elements 2964 index: function( elem ) { 2965 2966 // No argument, return index in parent 2967 if ( !elem ) { 2968 return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; 2969 } 2970 2971 // index in selector 2972 if ( typeof elem === "string" ) { 2973 return jQuery.inArray( this[0], jQuery( elem ) ); 2974 } 2975 2976 // Locate the position of the desired element 2977 return jQuery.inArray( 2978 // If it receives a jQuery object, the first element is used 2979 elem.jquery ? elem[0] : elem, this ); 2980 }, 2981 2982 add: function( selector, context ) { 2983 return this.pushStack( 2984 jQuery.unique( 2985 jQuery.merge( this.get(), jQuery( selector, context ) ) 2986 ) 2987 ); 2988 }, 2989 2990 addBack: function( selector ) { 2991 return this.add( selector == null ? 2992 this.prevObject : this.prevObject.filter(selector) 2993 ); 2994 } 2995}); 2996 2997function sibling( cur, dir ) { 2998 do { 2999 cur = cur[ dir ]; 3000 } while ( cur && cur.nodeType !== 1 ); 3001 3002 return cur; 3003} 3004 3005jQuery.each({ 3006 parent: function( elem ) { 3007 var parent = elem.parentNode; 3008 return parent && parent.nodeType !== 11 ? parent : null; 3009 }, 3010 parents: function( elem ) { 3011 return jQuery.dir( elem, "parentNode" ); 3012 }, 3013 parentsUntil: function( elem, i, until ) { 3014 return jQuery.dir( elem, "parentNode", until ); 3015 }, 3016 next: function( elem ) { 3017 return sibling( elem, "nextSibling" ); 3018 }, 3019 prev: function( elem ) { 3020 return sibling( elem, "previousSibling" ); 3021 }, 3022 nextAll: function( elem ) { 3023 return jQuery.dir( elem, "nextSibling" ); 3024 }, 3025 prevAll: function( elem ) { 3026 return jQuery.dir( elem, "previousSibling" ); 3027 }, 3028 nextUntil: function( elem, i, until ) { 3029 return jQuery.dir( elem, "nextSibling", until ); 3030 }, 3031 prevUntil: function( elem, i, until ) { 3032 return jQuery.dir( elem, "previousSibling", until ); 3033 }, 3034 siblings: function( elem ) { 3035 return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); 3036 }, 3037 children: function( elem ) { 3038 return jQuery.sibling( elem.firstChild ); 3039 }, 3040 contents: function( elem ) { 3041 return jQuery.nodeName( elem, "iframe" ) ? 3042 elem.contentDocument || elem.contentWindow.document : 3043 jQuery.merge( [], elem.childNodes ); 3044 } 3045}, function( name, fn ) { 3046 jQuery.fn[ name ] = function( until, selector ) { 3047 var ret = jQuery.map( this, fn, until ); 3048 3049 if ( name.slice( -5 ) !== "Until" ) { 3050 selector = until; 3051 } 3052 3053 if ( selector && typeof selector === "string" ) { 3054 ret = jQuery.filter( selector, ret ); 3055 } 3056 3057 if ( this.length > 1 ) { 3058 // Remove duplicates 3059 if ( !guaranteedUnique[ name ] ) { 3060 ret = jQuery.unique( ret ); 3061 } 3062 3063 // Reverse order for parents* and prev-derivatives 3064 if ( rparentsprev.test( name ) ) { 3065 ret = ret.reverse(); 3066 } 3067 } 3068 3069 return this.pushStack( ret ); 3070 }; 3071}); 3072var rnotwhite = (/\S+/g); 3073 3074 3075 3076// String to Object options format cache 3077var optionsCache = {}; 3078 3079// Convert String-formatted options into Object-formatted ones and store in cache 3080function createOptions( options ) { 3081 var object = optionsCache[ options ] = {}; 3082 jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { 3083 object[ flag ] = true; 3084 }); 3085 return object; 3086} 3087 3088/* 3089 * Create a callback list using the following parameters: 3090 * 3091 * options: an optional list of space-separated options that will change how 3092 * the callback list behaves or a more traditional option object 3093 * 3094 * By default a callback list will act like an event callback list and can be 3095 * "fired" multiple times. 3096 * 3097 * Possible options: 3098 * 3099 * once: will ensure the callback list can only be fired once (like a Deferred) 3100 * 3101 * memory: will keep track of previous values and will call any callback added 3102 * after the list has been fired right away with the latest "memorized" 3103 * values (like a Deferred) 3104 * 3105 * unique: will ensure a callback can only be added once (no duplicate in the list) 3106 * 3107 * stopOnFalse: interrupt callings when a callback returns false 3108 * 3109 */ 3110jQuery.Callbacks = function( options ) { 3111 3112 // Convert options from String-formatted to Object-formatted if needed 3113 // (we check in cache first) 3114 options = typeof options === "string" ? 3115 ( optionsCache[ options ] || createOptions( options ) ) : 3116 jQuery.extend( {}, options ); 3117 3118 var // Flag to know if list is currently firing 3119 firing, 3120 // Last fire value (for non-forgettable lists) 3121 memory, 3122 // Flag to know if list was already fired 3123 fired, 3124 // End of the loop when firing 3125 firingLength, 3126 // Index of currently firing callback (modified by remove if needed) 3127 firingIndex, 3128 // First callback to fire (used internally by add and fireWith) 3129 firingStart, 3130 // Actual callback list 3131 list = [], 3132 // Stack of fire calls for repeatable lists 3133 stack = !options.once && [], 3134 // Fire callbacks 3135 fire = function( data ) { 3136 memory = options.memory && data; 3137 fired = true; 3138 firingIndex = firingStart || 0; 3139 firingStart = 0; 3140 firingLength = list.length; 3141 firing = true; 3142 for ( ; list && firingIndex < firingLength; firingIndex++ ) { 3143 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { 3144 memory = false; // To prevent further calls using add 3145 break; 3146 } 3147 } 3148 firing = false; 3149 if ( list ) { 3150 if ( stack ) { 3151 if ( stack.length ) { 3152 fire( stack.shift() ); 3153 } 3154 } else if ( memory ) { 3155 list = []; 3156 } else { 3157 self.disable(); 3158 } 3159 } 3160 }, 3161 // Actual Callbacks object 3162 self = { 3163 // Add a callback or a collection of callbacks to the list 3164 add: function() { 3165 if ( list ) { 3166 // First, we save the current length 3167 var start = list.length; 3168 (function add( args ) { 3169 jQuery.each( args, function( _, arg ) { 3170 var type = jQuery.type( arg ); 3171 if ( type === "function" ) { 3172 if ( !options.unique || !self.has( arg ) ) { 3173 list.push( arg ); 3174 } 3175 } else if ( arg && arg.length && type !== "string" ) { 3176 // Inspect recursively 3177 add( arg ); 3178 } 3179 }); 3180 })( arguments ); 3181 // Do we need to add the callbacks to the 3182 // current firing batch? 3183 if ( firing ) { 3184 firingLength = list.length; 3185 // With memory, if we're not firing then 3186 // we should call right away 3187 } else if ( memory ) { 3188 firingStart = start; 3189 fire( memory ); 3190 } 3191 } 3192 return this; 3193 }, 3194 // Remove a callback from the list 3195 remove: function() { 3196 if ( list ) { 3197 jQuery.each( arguments, function( _, arg ) { 3198 var index; 3199 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { 3200 list.splice( index, 1 ); 3201 // Handle firing indexes 3202 if ( firing ) { 3203 if ( index <= firingLength ) { 3204 firingLength--; 3205 } 3206 if ( index <= firingIndex ) { 3207 firingIndex--; 3208 } 3209 } 3210 } 3211 }); 3212 } 3213 return this; 3214 }, 3215 // Check if a given callback is in the list. 3216 // If no argument is given, return whether or not list has callbacks attached. 3217 has: function( fn ) { 3218 return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); 3219 }, 3220 // Remove all callbacks from the list 3221 empty: function() { 3222 list = []; 3223 firingLength = 0; 3224 return this; 3225 }, 3226 // Have the list do nothing anymore 3227 disable: function() { 3228 list = stack = memory = undefined; 3229 return this; 3230 }, 3231 // Is it disabled? 3232 disabled: function() { 3233 return !list; 3234 }, 3235 // Lock the list in its current state 3236 lock: function() { 3237 stack = undefined; 3238 if ( !memory ) { 3239 self.disable(); 3240 } 3241 return this; 3242 }, 3243 // Is it locked? 3244 locked: function() { 3245 return !stack; 3246 }, 3247 // Call all callbacks with the given context and arguments 3248 fireWith: function( context, args ) { 3249 if ( list && ( !fired || stack ) ) { 3250 args = args || []; 3251 args = [ context, args.slice ? args.slice() : args ]; 3252 if ( firing ) { 3253 stack.push( args ); 3254 } else { 3255 fire( args ); 3256 } 3257 } 3258 return this; 3259 }, 3260 // Call all the callbacks with the given arguments 3261 fire: function() { 3262 self.fireWith( this, arguments ); 3263 return this; 3264 }, 3265 // To know if the callbacks have already been called at least once 3266 fired: function() { 3267 return !!fired; 3268 } 3269 }; 3270 3271 return self; 3272}; 3273 3274 3275jQuery.extend({ 3276 3277 Deferred: function( func ) { 3278 var tuples = [ 3279 // action, add listener, listener list, final state 3280 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], 3281 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], 3282 [ "notify", "progress", jQuery.Callbacks("memory") ] 3283 ], 3284 state = "pending", 3285 promise = { 3286 state: function() { 3287 return state; 3288 }, 3289 always: function() { 3290 deferred.done( arguments ).fail( arguments ); 3291 return this; 3292 }, 3293 then: function( /* fnDone, fnFail, fnProgress */ ) { 3294 var fns = arguments; 3295 return jQuery.Deferred(function( newDefer ) { 3296 jQuery.each( tuples, function( i, tuple ) { 3297 var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; 3298 // deferred[ done | fail | progress ] for forwarding actions to newDefer 3299 deferred[ tuple[1] ](function() { 3300 var returned = fn && fn.apply( this, arguments ); 3301 if ( returned && jQuery.isFunction( returned.promise ) ) { 3302 returned.promise() 3303 .done( newDefer.resolve ) 3304 .fail( newDefer.reject ) 3305 .progress( newDefer.notify ); 3306 } else { 3307 newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); 3308 } 3309 }); 3310 }); 3311 fns = null; 3312 }).promise(); 3313 }, 3314 // Get a promise for this deferred 3315 // If obj is provided, the promise aspect is added to the object 3316 promise: function( obj ) { 3317 return obj != null ? jQuery.extend( obj, promise ) : promise; 3318 } 3319 }, 3320 deferred = {}; 3321 3322 // Keep pipe for back-compat 3323 promise.pipe = promise.then; 3324 3325 // Add list-specific methods 3326 jQuery.each( tuples, function( i, tuple ) { 3327 var list = tuple[ 2 ], 3328 stateString = tuple[ 3 ]; 3329 3330 // promise[ done | fail | progress ] = list.add 3331 promise[ tuple[1] ] = list.add; 3332 3333 // Handle state 3334 if ( stateString ) { 3335 list.add(function() { 3336 // state = [ resolved | rejected ] 3337 state = stateString; 3338 3339 // [ reject_list | resolve_list ].disable; progress_list.lock 3340 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); 3341 } 3342 3343 // deferred[ resolve | reject | notify ] 3344 deferred[ tuple[0] ] = function() { 3345 deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); 3346 return this; 3347 }; 3348 deferred[ tuple[0] + "With" ] = list.fireWith; 3349 }); 3350 3351 // Make the deferred a promise 3352 promise.promise( deferred ); 3353 3354 // Call given func if any 3355 if ( func ) { 3356 func.call( deferred, deferred ); 3357 } 3358 3359 // All done! 3360 return deferred; 3361 }, 3362 3363 // Deferred helper 3364 when: function( subordinate /* , ..., subordinateN */ ) { 3365 var i = 0, 3366 resolveValues = slice.call( arguments ), 3367 length = resolveValues.length, 3368 3369 // the count of uncompleted subordinates 3370 remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, 3371 3372 // the master Deferred. If resolveValues consist of only a single Deferred, just use that. 3373 deferred = remaining === 1 ? subordinate : jQuery.Deferred(), 3374 3375 // Update function for both resolve and progress values 3376 updateFunc = function( i, contexts, values ) { 3377 return function( value ) { 3378 contexts[ i ] = this; 3379 values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; 3380 if ( values === progressValues ) { 3381 deferred.notifyWith( contexts, values ); 3382 3383 } else if ( !(--remaining) ) { 3384 deferred.resolveWith( contexts, values ); 3385 } 3386 }; 3387 }, 3388 3389 progressValues, progressContexts, resolveContexts; 3390 3391 // add listeners to Deferred subordinates; treat others as resolved 3392 if ( length > 1 ) { 3393 progressValues = new Array( length ); 3394 progressContexts = new Array( length ); 3395 resolveContexts = new Array( length ); 3396 for ( ; i < length; i++ ) { 3397 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { 3398 resolveValues[ i ].promise() 3399 .done( updateFunc( i, resolveContexts, resolveValues ) ) 3400 .fail( deferred.reject ) 3401 .progress( updateFunc( i, progressContexts, progressValues ) ); 3402 } else { 3403 --remaining; 3404 } 3405 } 3406 } 3407 3408 // if we're not waiting on anything, resolve the master 3409 if ( !remaining ) { 3410 deferred.resolveWith( resolveContexts, resolveValues ); 3411 } 3412 3413 return deferred.promise(); 3414 } 3415}); 3416 3417 3418// The deferred used on DOM ready 3419var readyList; 3420 3421jQuery.fn.ready = function( fn ) { 3422 // Add the callback 3423 jQuery.ready.promise().done( fn ); 3424 3425 return this; 3426}; 3427 3428jQuery.extend({ 3429 // Is the DOM ready to be used? Set to true once it occurs. 3430 isReady: false, 3431 3432 // A counter to track how many items to wait for before 3433 // the ready event fires. See #6781 3434 readyWait: 1, 3435 3436 // Hold (or release) the ready event 3437 holdReady: function( hold ) { 3438 if ( hold ) { 3439 jQuery.readyWait++; 3440 } else { 3441 jQuery.ready( true ); 3442 } 3443 }, 3444 3445 // Handle when the DOM is ready 3446 ready: function( wait ) { 3447 3448 // Abort if there are pending holds or we're already ready 3449 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { 3450 return; 3451 } 3452 3453 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). 3454 if ( !document.body ) { 3455 return setTimeout( jQuery.ready ); 3456 } 3457 3458 // Remember that the DOM is ready 3459 jQuery.isReady = true; 3460 3461 // If a normal DOM Ready event fired, decrement, and wait if need be 3462 if ( wait !== true && --jQuery.readyWait > 0 ) { 3463 return; 3464 } 3465 3466 // If there are functions bound, to execute 3467 readyList.resolveWith( document, [ jQuery ] ); 3468 3469 // Trigger any bound ready events 3470 if ( jQuery.fn.triggerHandler ) { 3471 jQuery( document ).triggerHandler( "ready" ); 3472 jQuery( document ).off( "ready" ); 3473 } 3474 } 3475}); 3476 3477/** 3478 * Clean-up method for dom ready events 3479 */ 3480function detach() { 3481 if ( document.addEventListener ) { 3482 document.removeEventListener( "DOMContentLoaded", completed, false ); 3483 window.removeEventListener( "load", completed, false ); 3484 3485 } else { 3486 document.detachEvent( "onreadystatechange", completed ); 3487 window.detachEvent( "onload", completed ); 3488 } 3489} 3490 3491/** 3492 * The ready event handler and self cleanup method 3493 */ 3494function completed() { 3495 // readyState === "complete" is good enough for us to call the dom ready in oldIE 3496 if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { 3497 detach(); 3498 jQuery.ready(); 3499 } 3500} 3501 3502jQuery.ready.promise = function( obj ) { 3503 if ( !readyList ) { 3504 3505 readyList = jQuery.Deferred(); 3506 3507 // Catch cases where $(document).ready() is called after the browser event has already occurred. 3508 // we once tried to use readyState "interactive" here, but it caused issues like the one 3509 // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 3510 if ( document.readyState === "complete" ) { 3511 // Handle it asynchronously to allow scripts the opportunity to delay ready 3512 setTimeout( jQuery.ready ); 3513 3514 // Standards-based browsers support DOMContentLoaded 3515 } else if ( document.addEventListener ) { 3516 // Use the handy event callback 3517 document.addEventListener( "DOMContentLoaded", completed, false ); 3518 3519 // A fallback to window.onload, that will always work 3520 window.addEventListener( "load", completed, false ); 3521 3522 // If IE event model is used 3523 } else { 3524 // Ensure firing before onload, maybe late but safe also for iframes 3525 document.attachEvent( "onreadystatechange", completed ); 3526 3527 // A fallback to window.onload, that will always work 3528 window.attachEvent( "onload", completed ); 3529 3530 // If IE and not a frame 3531 // continually check to see if the document is ready 3532 var top = false; 3533 3534 try { 3535 top = window.frameElement == null && document.documentElement; 3536 } catch(e) {} 3537 3538 if ( top && top.doScroll ) { 3539 (function doScrollCheck() { 3540 if ( !jQuery.isReady ) { 3541 3542 try { 3543 // Use the trick by Diego Perini 3544 // http://javascript.nwbox.com/IEContentLoaded/ 3545 top.doScroll("left"); 3546 } catch(e) { 3547 return setTimeout( doScrollCheck, 50 ); 3548 } 3549 3550 // detach all dom ready events 3551 detach(); 3552 3553 // and execute any waiting functions 3554 jQuery.ready(); 3555 } 3556 })(); 3557 } 3558 } 3559 } 3560 return readyList.promise( obj ); 3561}; 3562 3563 3564var strundefined = typeof undefined; 3565 3566 3567 3568// Support: IE<9 3569// Iteration over object's inherited properties before its own 3570var i; 3571for ( i in jQuery( support ) ) { 3572 break; 3573} 3574support.ownLast = i !== "0"; 3575 3576// Note: most support tests are defined in their respective modules. 3577// false until the test is run 3578support.inlineBlockNeedsLayout = false; 3579 3580// Execute ASAP in case we need to set body.style.zoom 3581jQuery(function() { 3582 // Minified: var a,b,c,d 3583 var val, div, body, container; 3584 3585 body = document.getElementsByTagName( "body" )[ 0 ]; 3586 if ( !body || !body.style ) { 3587 // Return for frameset docs that don't have a body 3588 return; 3589 } 3590 3591 // Setup 3592 div = document.createElement( "div" ); 3593 container = document.createElement( "div" ); 3594 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; 3595 body.appendChild( container ).appendChild( div ); 3596 3597 if ( typeof div.style.zoom !== strundefined ) { 3598 // Support: IE<8 3599 // Check if natively block-level elements act like inline-block 3600 // elements when setting their display to 'inline' and giving 3601 // them layout 3602 div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; 3603 3604 support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; 3605 if ( val ) { 3606 // Prevent IE 6 from affecting layout for positioned elements #11048 3607 // Prevent IE from shrinking the body in IE 7 mode #12869 3608 // Support: IE<8 3609 body.style.zoom = 1; 3610 } 3611 } 3612 3613 body.removeChild( container ); 3614}); 3615 3616 3617 3618 3619(function() { 3620 var div = document.createElement( "div" ); 3621 3622 // Execute the test only if not already executed in another module. 3623 if (support.deleteExpando == null) { 3624 // Support: IE<9 3625 support.deleteExpando = true; 3626 try { 3627 delete div.test; 3628 } catch( e ) { 3629 support.deleteExpando = false; 3630 } 3631 } 3632 3633 // Null elements to avoid leaks in IE. 3634 div = null; 3635})(); 3636 3637 3638/** 3639 * Determines whether an object can have data 3640 */ 3641jQuery.acceptData = function( elem ) { 3642 var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ], 3643 nodeType = +elem.nodeType || 1; 3644 3645 // Do not set data on non-element DOM nodes because it will not be cleared (#8335). 3646 return nodeType !== 1 && nodeType !== 9 ? 3647 false : 3648 3649 // Nodes accept data unless otherwise specified; rejection can be conditional 3650 !noData || noData !== true && elem.getAttribute("classid") === noData; 3651}; 3652 3653 3654var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, 3655 rmultiDash = /([A-Z])/g; 3656 3657function dataAttr( elem, key, data ) { 3658 // If nothing was found internally, try to fetch any 3659 // data from the HTML5 data-* attribute 3660 if ( data === undefined && elem.nodeType === 1 ) { 3661 3662 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); 3663 3664 data = elem.getAttribute( name ); 3665 3666 if ( typeof data === "string" ) { 3667 try { 3668 data = data === "true" ? true : 3669 data === "false" ? false : 3670 data === "null" ? null : 3671 // Only convert to a number if it doesn't change the string 3672 +data + "" === data ? +data : 3673 rbrace.test( data ) ? jQuery.parseJSON( data ) : 3674 data; 3675 } catch( e ) {} 3676 3677 // Make sure we set the data so it isn't changed later 3678 jQuery.data( elem, key, data ); 3679 3680 } else { 3681 data = undefined; 3682 } 3683 } 3684 3685 return data; 3686} 3687 3688// checks a cache object for emptiness 3689function isEmptyDataObject( obj ) { 3690 var name; 3691 for ( name in obj ) { 3692 3693 // if the public data object is empty, the private is still empty 3694 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { 3695 continue; 3696 } 3697 if ( name !== "toJSON" ) { 3698 return false; 3699 } 3700 } 3701 3702 return true; 3703} 3704 3705function internalData( elem, name, data, pvt /* Internal Use Only */ ) { 3706 if ( !jQuery.acceptData( elem ) ) { 3707 return; 3708 } 3709 3710 var ret, thisCache, 3711 internalKey = jQuery.expando, 3712 3713 // We have to handle DOM nodes and JS objects differently because IE6-7 3714 // can't GC object references properly across the DOM-JS boundary 3715 isNode = elem.nodeType, 3716 3717 // Only DOM nodes need the global jQuery cache; JS object data is 3718 // attached directly to the object so GC can occur automatically 3719 cache = isNode ? jQuery.cache : elem, 3720 3721 // Only defining an ID for JS objects if its cache already exists allows 3722 // the code to shortcut on the same path as a DOM node with no cache 3723 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; 3724 3725 // Avoid doing any more work than we need to when trying to get data on an 3726 // object that has no data at all 3727 if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { 3728 return; 3729 } 3730 3731 if ( !id ) { 3732 // Only DOM nodes need a new unique ID for each element since their data 3733 // ends up in the global cache 3734 if ( isNode ) { 3735 id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++; 3736 } else { 3737 id = internalKey; 3738 } 3739 } 3740 3741 if ( !cache[ id ] ) { 3742 // Avoid exposing jQuery metadata on plain JS objects when the object 3743 // is serialized using JSON.stringify 3744 cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; 3745 } 3746 3747 // An object can be passed to jQuery.data instead of a key/value pair; this gets 3748 // shallow copied over onto the existing cache 3749 if ( typeof name === "object" || typeof name === "function" ) { 3750 if ( pvt ) { 3751 cache[ id ] = jQuery.extend( cache[ id ], name ); 3752 } else { 3753 cache[ id ].data = jQuery.extend( cache[ id ].data, name ); 3754 } 3755 } 3756 3757 thisCache = cache[ id ]; 3758 3759 // jQuery data() is stored in a separate object inside the object's internal data 3760 // cache in order to avoid key collisions between internal data and user-defined 3761 // data. 3762 if ( !pvt ) { 3763 if ( !thisCache.data ) { 3764 thisCache.data = {}; 3765 } 3766 3767 thisCache = thisCache.data; 3768 } 3769 3770 if ( data !== undefined ) { 3771 thisCache[ jQuery.camelCase( name ) ] = data; 3772 } 3773 3774 // Check for both converted-to-camel and non-converted data property names 3775 // If a data property was specified 3776 if ( typeof name === "string" ) { 3777 3778 // First Try to find as-is property data 3779 ret = thisCache[ name ]; 3780 3781 // Test for null|undefined property data 3782 if ( ret == null ) { 3783 3784 // Try to find the camelCased property 3785 ret = thisCache[ jQuery.camelCase( name ) ]; 3786 } 3787 } else { 3788 ret = thisCache; 3789 } 3790 3791 return ret; 3792} 3793 3794function internalRemoveData( elem, name, pvt ) { 3795 if ( !jQuery.acceptData( elem ) ) { 3796 return; 3797 } 3798 3799 var thisCache, i, 3800 isNode = elem.nodeType, 3801 3802 // See jQuery.data for more information 3803 cache = isNode ? jQuery.cache : elem, 3804 id = isNode ? elem[ jQuery.expando ] : jQuery.expando; 3805 3806 // If there is already no cache entry for this object, there is no 3807 // purpose in continuing 3808 if ( !cache[ id ] ) { 3809 return; 3810 } 3811 3812 if ( name ) { 3813 3814 thisCache = pvt ? cache[ id ] : cache[ id ].data; 3815 3816 if ( thisCache ) { 3817 3818 // Support array or space separated string names for data keys 3819 if ( !jQuery.isArray( name ) ) { 3820 3821 // try the string as a key before any manipulation 3822 if ( name in thisCache ) { 3823 name = [ name ]; 3824 } else { 3825 3826 // split the camel cased version by spaces unless a key with the spaces exists 3827 name = jQuery.camelCase( name ); 3828 if ( name in thisCache ) { 3829 name = [ name ]; 3830 } else { 3831 name = name.split(" "); 3832 } 3833 } 3834 } else { 3835 // If "name" is an array of keys... 3836 // When data is initially created, via ("key", "val") signature, 3837 // keys will be converted to camelCase. 3838 // Since there is no way to tell _how_ a key was added, remove 3839 // both plain key and camelCase key. #12786 3840 // This will only penalize the array argument path. 3841 name = name.concat( jQuery.map( name, jQuery.camelCase ) ); 3842 } 3843 3844 i = name.length; 3845 while ( i-- ) { 3846 delete thisCache[ name[i] ]; 3847 } 3848 3849 // If there is no data left in the cache, we want to continue 3850 // and let the cache object itself get destroyed 3851 if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { 3852 return; 3853 } 3854 } 3855 } 3856 3857 // See jQuery.data for more information 3858 if ( !pvt ) { 3859 delete cache[ id ].data; 3860 3861 // Don't destroy the parent cache unless the internal data object 3862 // had been the only thing left in it 3863 if ( !isEmptyDataObject( cache[ id ] ) ) { 3864 return; 3865 } 3866 } 3867 3868 // Destroy the cache 3869 if ( isNode ) { 3870 jQuery.cleanData( [ elem ], true ); 3871 3872 // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) 3873 /* jshint eqeqeq: false */ 3874 } else if ( support.deleteExpando || cache != cache.window ) { 3875 /* jshint eqeqeq: true */ 3876 delete cache[ id ]; 3877 3878 // When all else fails, null 3879 } else { 3880 cache[ id ] = null; 3881 } 3882} 3883 3884jQuery.extend({ 3885 cache: {}, 3886 3887 // The following elements (space-suffixed to avoid Object.prototype collisions) 3888 // throw uncatchable exceptions if you attempt to set expando properties 3889 noData: { 3890 "applet ": true, 3891 "embed ": true, 3892 // ...but Flash objects (which have this classid) *can* handle expandos 3893 "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" 3894 }, 3895 3896 hasData: function( elem ) { 3897 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; 3898 return !!elem && !isEmptyDataObject( elem ); 3899 }, 3900 3901 data: function( elem, name, data ) { 3902 return internalData( elem, name, data ); 3903 }, 3904 3905 removeData: function( elem, name ) { 3906 return internalRemoveData( elem, name ); 3907 }, 3908 3909 // For internal use only. 3910 _data: function( elem, name, data ) { 3911 return internalData( elem, name, data, true ); 3912 }, 3913 3914 _removeData: function( elem, name ) { 3915 return internalRemoveData( elem, name, true ); 3916 } 3917}); 3918 3919jQuery.fn.extend({ 3920 data: function( key, value ) { 3921 var i, name, data, 3922 elem = this[0], 3923 attrs = elem && elem.attributes; 3924 3925 // Special expections of .data basically thwart jQuery.access, 3926 // so implement the relevant behavior ourselves 3927 3928 // Gets all values 3929 if ( key === undefined ) { 3930 if ( this.length ) { 3931 data = jQuery.data( elem ); 3932 3933 if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { 3934 i = attrs.length; 3935 while ( i-- ) { 3936 3937 // Support: IE11+ 3938 // The attrs elements can be null (#14894) 3939 if ( attrs[ i ] ) { 3940 name = attrs[ i ].name; 3941 if ( name.indexOf( "data-" ) === 0 ) { 3942 name = jQuery.camelCase( name.slice(5) ); 3943 dataAttr( elem, name, data[ name ] ); 3944 } 3945 } 3946 } 3947 jQuery._data( elem, "parsedAttrs", true ); 3948 } 3949 } 3950 3951 return data; 3952 } 3953 3954 // Sets multiple values 3955 if ( typeof key === "object" ) { 3956 return this.each(function() { 3957 jQuery.data( this, key ); 3958 }); 3959 } 3960 3961 return arguments.length > 1 ? 3962 3963 // Sets one value 3964 this.each(function() { 3965 jQuery.data( this, key, value ); 3966 }) : 3967 3968 // Gets one value 3969 // Try to fetch any internally stored data first 3970 elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; 3971 }, 3972 3973 removeData: function( key ) { 3974 return this.each(function() { 3975 jQuery.removeData( this, key ); 3976 }); 3977 } 3978}); 3979 3980 3981jQuery.extend({ 3982 queue: function( elem, type, data ) { 3983 var queue; 3984 3985 if ( elem ) { 3986 type = ( type || "fx" ) + "queue"; 3987 queue = jQuery._data( elem, type ); 3988 3989 // Speed up dequeue by getting out quickly if this is just a lookup 3990 if ( data ) { 3991 if ( !queue || jQuery.isArray(data) ) { 3992 queue = jQuery._data( elem, type, jQuery.makeArray(data) ); 3993 } else { 3994 queue.push( data ); 3995 } 3996 } 3997 return queue || []; 3998 } 3999 }, 4000 4001 dequeue: function( elem, type ) { 4002 type = type || "fx"; 4003 4004 var queue = jQuery.queue( elem, type ), 4005 startLength = queue.length, 4006 fn = queue.shift(), 4007 hooks = jQuery._queueHooks( elem, type ), 4008 next = function() { 4009 jQuery.dequeue( elem, type ); 4010 }; 4011 4012 // If the fx queue is dequeued, always remove the progress sentinel 4013 if ( fn === "inprogress" ) { 4014 fn = queue.shift(); 4015 startLength--; 4016 } 4017 4018 if ( fn ) { 4019 4020 // Add a progress sentinel to prevent the fx queue from being 4021 // automatically dequeued 4022 if ( type === "fx" ) { 4023 queue.unshift( "inprogress" ); 4024 } 4025 4026 // clear up the last queue stop function 4027 delete hooks.stop; 4028 fn.call( elem, next, hooks ); 4029 } 4030 4031 if ( !startLength && hooks ) { 4032 hooks.empty.fire(); 4033 } 4034 }, 4035 4036 // not intended for public consumption - generates a queueHooks object, or returns the current one 4037 _queueHooks: function( elem, type ) { 4038 var key = type + "queueHooks"; 4039 return jQuery._data( elem, key ) || jQuery._data( elem, key, { 4040 empty: jQuery.Callbacks("once memory").add(function() { 4041 jQuery._removeData( elem, type + "queue" ); 4042 jQuery._removeData( elem, key ); 4043 }) 4044 }); 4045 } 4046}); 4047 4048jQuery.fn.extend({ 4049 queue: function( type, data ) { 4050 var setter = 2; 4051 4052 if ( typeof type !== "string" ) { 4053 data = type; 4054 type = "fx"; 4055 setter--; 4056 } 4057 4058 if ( arguments.length < setter ) { 4059 return jQuery.queue( this[0], type ); 4060 } 4061 4062 return data === undefined ? 4063 this : 4064 this.each(function() { 4065 var queue = jQuery.queue( this, type, data ); 4066 4067 // ensure a hooks for this queue 4068 jQuery._queueHooks( this, type ); 4069 4070 if ( type === "fx" && queue[0] !== "inprogress" ) { 4071 jQuery.dequeue( this, type ); 4072 } 4073 }); 4074 }, 4075 dequeue: function( type ) { 4076 return this.each(function() { 4077 jQuery.dequeue( this, type ); 4078 }); 4079 }, 4080 clearQueue: function( type ) { 4081 return this.queue( type || "fx", [] ); 4082 }, 4083 // Get a promise resolved when queues of a certain type 4084 // are emptied (fx is the type by default) 4085 promise: function( type, obj ) { 4086 var tmp, 4087 count = 1, 4088 defer = jQuery.Deferred(), 4089 elements = this, 4090 i = this.length, 4091 resolve = function() { 4092 if ( !( --count ) ) { 4093 defer.resolveWith( elements, [ elements ] ); 4094 } 4095 }; 4096 4097 if ( typeof type !== "string" ) { 4098 obj = type; 4099 type = undefined; 4100 } 4101 type = type || "fx"; 4102 4103 while ( i-- ) { 4104 tmp = jQuery._data( elements[ i ], type + "queueHooks" ); 4105 if ( tmp && tmp.empty ) { 4106 count++; 4107 tmp.empty.add( resolve ); 4108 } 4109 } 4110 resolve(); 4111 return defer.promise( obj ); 4112 } 4113}); 4114var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; 4115 4116var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; 4117 4118var isHidden = function( elem, el ) { 4119 // isHidden might be called from jQuery#filter function; 4120 // in that case, element will be second argument 4121 elem = el || elem; 4122 return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); 4123 }; 4124 4125 4126 4127// Multifunctional method to get and set values of a collection 4128// The value/s can optionally be executed if it's a function 4129var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { 4130 var i = 0, 4131 length = elems.length, 4132 bulk = key == null; 4133 4134 // Sets many values 4135 if ( jQuery.type( key ) === "object" ) { 4136 chainable = true; 4137 for ( i in key ) { 4138 jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); 4139 } 4140 4141 // Sets one value 4142 } else if ( value !== undefined ) { 4143 chainable = true; 4144 4145 if ( !jQuery.isFunction( value ) ) { 4146 raw = true; 4147 } 4148 4149 if ( bulk ) { 4150 // Bulk operations run against the entire set 4151 if ( raw ) { 4152 fn.call( elems, value ); 4153 fn = null; 4154 4155 // ...except when executing function values 4156 } else { 4157 bulk = fn; 4158 fn = function( elem, key, value ) { 4159 return bulk.call( jQuery( elem ), value ); 4160 }; 4161 } 4162 } 4163 4164 if ( fn ) { 4165 for ( ; i < length; i++ ) { 4166 fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); 4167 } 4168 } 4169 } 4170 4171 return chainable ? 4172 elems : 4173 4174 // Gets 4175 bulk ? 4176 fn.call( elems ) : 4177 length ? fn( elems[0], key ) : emptyGet; 4178}; 4179var rcheckableType = (/^(?:checkbox|radio)$/i); 4180 4181 4182 4183(function() { 4184 // Minified: var a,b,c 4185 var input = document.createElement( "input" ), 4186 div = document.createElement( "div" ), 4187 fragment = document.createDocumentFragment(); 4188 4189 // Setup 4190 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; 4191 4192 // IE strips leading whitespace when .innerHTML is used 4193 support.leadingWhitespace = div.firstChild.nodeType === 3; 4194 4195 // Make sure that tbody elements aren't automatically inserted 4196 // IE will insert them into empty tables 4197 support.tbody = !div.getElementsByTagName( "tbody" ).length; 4198 4199 // Make sure that link elements get serialized correctly by innerHTML 4200 // This requires a wrapper element in IE 4201 support.htmlSerialize = !!div.getElementsByTagName( "link" ).length; 4202 4203 // Makes sure cloning an html5 element does not cause problems 4204 // Where outerHTML is undefined, this still works 4205 support.html5Clone = 4206 document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>"; 4207 4208 // Check if a disconnected checkbox will retain its checked 4209 // value of true after appended to the DOM (IE6/7) 4210 input.type = "checkbox"; 4211 input.checked = true; 4212 fragment.appendChild( input ); 4213 support.appendChecked = input.checked; 4214 4215 // Make sure textarea (and checkbox) defaultValue is properly cloned 4216 // Support: IE6-IE11+ 4217 div.innerHTML = "<textarea>x</textarea>"; 4218 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; 4219 4220 // #11217 - WebKit loses check when the name is after the checked attribute 4221 fragment.appendChild( div ); 4222 div.innerHTML = "<input type='radio' checked='checked' name='t'/>"; 4223 4224 // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 4225 // old WebKit doesn't clone checked state correctly in fragments 4226 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; 4227 4228 // Support: IE<9 4229 // Opera does not clone events (and typeof div.attachEvent === undefined). 4230 // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() 4231 support.noCloneEvent = true; 4232 if ( div.attachEvent ) { 4233 div.attachEvent( "onclick", function() { 4234 support.noCloneEvent = false; 4235 }); 4236 4237 div.cloneNode( true ).click(); 4238 } 4239 4240 // Execute the test only if not already executed in another module. 4241 if (support.deleteExpando == null) { 4242 // Support: IE<9 4243 support.deleteExpando = true; 4244 try { 4245 delete div.test; 4246 } catch( e ) { 4247 support.deleteExpando = false; 4248 } 4249 } 4250})(); 4251 4252 4253(function() { 4254 var i, eventName, 4255 div = document.createElement( "div" ); 4256 4257 // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event) 4258 for ( i in { submit: true, change: true, focusin: true }) { 4259 eventName = "on" + i; 4260 4261 if ( !(support[ i + "Bubbles" ] = eventName in window) ) { 4262 // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) 4263 div.setAttribute( eventName, "t" ); 4264 support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false; 4265 } 4266 } 4267 4268 // Null elements to avoid leaks in IE. 4269 div = null; 4270})(); 4271 4272 4273var rformElems = /^(?:input|select|textarea)$/i, 4274 rkeyEvent = /^key/, 4275 rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, 4276 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, 4277 rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; 4278 4279function returnTrue() { 4280 return true; 4281} 4282 4283function returnFalse() { 4284 return false; 4285} 4286 4287function safeActiveElement() { 4288 try { 4289 return document.activeElement; 4290 } catch ( err ) { } 4291} 4292 4293/* 4294 * Helper functions for managing events -- not part of the public interface. 4295 * Props to Dean Edwards' addEvent library for many of the ideas. 4296 */ 4297jQuery.event = { 4298 4299 global: {}, 4300 4301 add: function( elem, types, handler, data, selector ) { 4302 var tmp, events, t, handleObjIn, 4303 special, eventHandle, handleObj, 4304 handlers, type, namespaces, origType, 4305 elemData = jQuery._data( elem ); 4306 4307 // Don't attach events to noData or text/comment nodes (but allow plain objects) 4308 if ( !elemData ) { 4309 return; 4310 } 4311 4312 // Caller can pass in an object of custom data in lieu of the handler 4313 if ( handler.handler ) { 4314 handleObjIn = handler; 4315 handler = handleObjIn.handler; 4316 selector = handleObjIn.selector; 4317 } 4318 4319 // Make sure that the handler has a unique ID, used to find/remove it later 4320 if ( !handler.guid ) { 4321 handler.guid = jQuery.guid++; 4322 } 4323 4324 // Init the element's event structure and main handler, if this is the first 4325 if ( !(events = elemData.events) ) { 4326 events = elemData.events = {}; 4327 } 4328 if ( !(eventHandle = elemData.handle) ) { 4329 eventHandle = elemData.handle = function( e ) { 4330 // Discard the second event of a jQuery.event.trigger() and 4331 // when an event is called after a page has unloaded 4332 return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ? 4333 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : 4334 undefined; 4335 }; 4336 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events 4337 eventHandle.elem = elem; 4338 } 4339 4340 // Handle multiple events separated by a space 4341 types = ( types || "" ).match( rnotwhite ) || [ "" ]; 4342 t = types.length; 4343 while ( t-- ) { 4344 tmp = rtypenamespace.exec( types[t] ) || []; 4345 type = origType = tmp[1]; 4346 namespaces = ( tmp[2] || "" ).split( "." ).sort(); 4347 4348 // There *must* be a type, no attaching namespace-only handlers 4349 if ( !type ) { 4350 continue; 4351 } 4352 4353 // If event changes its type, use the special event handlers for the changed type 4354 special = jQuery.event.special[ type ] || {}; 4355 4356 // If selector defined, determine special event api type, otherwise given type 4357 type = ( selector ? special.delegateType : special.bindType ) || type; 4358 4359 // Update special based on newly reset type 4360 special = jQuery.event.special[ type ] || {}; 4361 4362 // handleObj is passed to all event handlers 4363 handleObj = jQuery.extend({ 4364 type: type, 4365 origType: origType, 4366 data: data, 4367 handler: handler, 4368 guid: handler.guid, 4369 selector: selector, 4370 needsContext: selector && jQuery.expr.match.needsContext.test( selector ), 4371 namespace: namespaces.join(".") 4372 }, handleObjIn ); 4373 4374 // Init the event handler queue if we're the first 4375 if ( !(handlers = events[ type ]) ) { 4376 handlers = events[ type ] = []; 4377 handlers.delegateCount = 0; 4378 4379 // Only use addEventListener/attachEvent if the special events handler returns false 4380 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { 4381 // Bind the global event handler to the element 4382 if ( elem.addEventListener ) { 4383 elem.addEventListener( type, eventHandle, false ); 4384 4385 } else if ( elem.attachEvent ) { 4386 elem.attachEvent( "on" + type, eventHandle ); 4387 } 4388 } 4389 } 4390 4391 if ( special.add ) { 4392 special.add.call( elem, handleObj ); 4393 4394 if ( !handleObj.handler.guid ) { 4395 handleObj.handler.guid = handler.guid; 4396 } 4397 } 4398 4399 // Add to the element's handler list, delegates in front 4400 if ( selector ) { 4401 handlers.splice( handlers.delegateCount++, 0, handleObj ); 4402 } else { 4403 handlers.push( handleObj ); 4404 } 4405 4406 // Keep track of which events have ever been used, for event optimization 4407 jQuery.event.global[ type ] = true; 4408 } 4409 4410 // Nullify elem to prevent memory leaks in IE 4411 elem = null; 4412 }, 4413 4414 // Detach an event or set of events from an element 4415 remove: function( elem, types, handler, selector, mappedTypes ) { 4416 var j, handleObj, tmp, 4417 origCount, t, events, 4418 special, handlers, type, 4419 namespaces, origType, 4420 elemData = jQuery.hasData( elem ) && jQuery._data( elem ); 4421 4422 if ( !elemData || !(events = elemData.events) ) { 4423 return; 4424 } 4425 4426 // Once for each type.namespace in types; type may be omitted 4427 types = ( types || "" ).match( rnotwhite ) || [ "" ]; 4428 t = types.length; 4429 while ( t-- ) { 4430 tmp = rtypenamespace.exec( types[t] ) || []; 4431 type = origType = tmp[1]; 4432 namespaces = ( tmp[2] || "" ).split( "." ).sort(); 4433 4434 // Unbind all events (on this namespace, if provided) for the element 4435 if ( !type ) { 4436 for ( type in events ) { 4437 jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); 4438 } 4439 continue; 4440 } 4441 4442 special = jQuery.event.special[ type ] || {}; 4443 type = ( selector ? special.delegateType : special.bindType ) || type; 4444 handlers = events[ type ] || []; 4445 tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); 4446 4447 // Remove matching events 4448 origCount = j = handlers.length; 4449 while ( j-- ) { 4450 handleObj = handlers[ j ]; 4451 4452 if ( ( mappedTypes || origType === handleObj.origType ) && 4453 ( !handler || handler.guid === handleObj.guid ) && 4454 ( !tmp || tmp.test( handleObj.namespace ) ) && 4455 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { 4456 handlers.splice( j, 1 ); 4457 4458 if ( handleObj.selector ) { 4459 handlers.delegateCount--; 4460 } 4461 if ( special.remove ) { 4462 special.remove.call( elem, handleObj ); 4463 } 4464 } 4465 } 4466 4467 // Remove generic event handler if we removed something and no more handlers exist 4468 // (avoids potential for endless recursion during removal of special event handlers) 4469 if ( origCount && !handlers.length ) { 4470 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { 4471 jQuery.removeEvent( elem, type, elemData.handle ); 4472 } 4473 4474 delete events[ type ]; 4475 } 4476 } 4477 4478 // Remove the expando if it's no longer used 4479 if ( jQuery.isEmptyObject( events ) ) { 4480 delete elemData.handle; 4481 4482 // removeData also checks for emptiness and clears the expando if empty 4483 // so use it instead of delete 4484 jQuery._removeData( elem, "events" ); 4485 } 4486 }, 4487 4488 trigger: function( event, data, elem, onlyHandlers ) { 4489 var handle, ontype, cur, 4490 bubbleType, special, tmp, i, 4491 eventPath = [ elem || document ], 4492 type = hasOwn.call( event, "type" ) ? event.type : event, 4493 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; 4494 4495 cur = tmp = elem = elem || document; 4496 4497 // Don't do events on text and comment nodes 4498 if ( elem.nodeType === 3 || elem.nodeType === 8 ) { 4499 return; 4500 } 4501 4502 // focus/blur morphs to focusin/out; ensure we're not firing them right now 4503 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { 4504 return; 4505 } 4506 4507 if ( type.indexOf(".") >= 0 ) { 4508 // Namespaced trigger; create a regexp to match event type in handle() 4509 namespaces = type.split("."); 4510 type = namespaces.shift(); 4511 namespaces.sort(); 4512 } 4513 ontype = type.indexOf(":") < 0 && "on" + type; 4514 4515 // Caller can pass in a jQuery.Event object, Object, or just an event type string 4516 event = event[ jQuery.expando ] ? 4517 event : 4518 new jQuery.Event( type, typeof event === "object" && event ); 4519 4520 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) 4521 event.isTrigger = onlyHandlers ? 2 : 3; 4522 event.namespace = namespaces.join("."); 4523 event.namespace_re = event.namespace ? 4524 new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : 4525 null; 4526 4527 // Clean up the event in case it is being reused 4528 event.result = undefined; 4529 if ( !event.target ) { 4530 event.target = elem; 4531 } 4532 4533 // Clone any incoming data and prepend the event, creating the handler arg list 4534 data = data == null ? 4535 [ event ] : 4536 jQuery.makeArray( data, [ event ] ); 4537 4538 // Allow special events to draw outside the lines 4539 special = jQuery.event.special[ type ] || {}; 4540 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { 4541 return; 4542 } 4543 4544 // Determine event propagation path in advance, per W3C events spec (#9951) 4545 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) 4546 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { 4547 4548 bubbleType = special.delegateType || type; 4549 if ( !rfocusMorph.test( bubbleType + type ) ) { 4550 cur = cur.parentNode; 4551 } 4552 for ( ; cur; cur = cur.parentNode ) { 4553 eventPath.push( cur ); 4554 tmp = cur; 4555 } 4556 4557 // Only add window if we got to document (e.g., not plain obj or detached DOM) 4558 if ( tmp === (elem.ownerDocument || document) ) { 4559 eventPath.push( tmp.defaultView || tmp.parentWindow || window ); 4560 } 4561 } 4562 4563 // Fire handlers on the event path 4564 i = 0; 4565 while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { 4566 4567 event.type = i > 1 ? 4568 bubbleType : 4569 special.bindType || type; 4570 4571 // jQuery handler 4572 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); 4573 if ( handle ) { 4574 handle.apply( cur, data ); 4575 } 4576 4577 // Native handler 4578 handle = ontype && cur[ ontype ]; 4579 if ( handle && handle.apply && jQuery.acceptData( cur ) ) { 4580 event.result = handle.apply( cur, data ); 4581 if ( event.result === false ) { 4582 event.preventDefault(); 4583 } 4584 } 4585 } 4586 event.type = type; 4587 4588 // If nobody prevented the default action, do it now 4589 if ( !onlyHandlers && !event.isDefaultPrevented() ) { 4590 4591 if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && 4592 jQuery.acceptData( elem ) ) { 4593 4594 // Call a native DOM method on the target with the same name name as the event. 4595 // Can't use an .isFunction() check here because IE6/7 fails that test. 4596 // Don't do default actions on window, that's where global variables be (#6170) 4597 if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { 4598 4599 // Don't re-trigger an onFOO event when we call its FOO() method 4600 tmp = elem[ ontype ]; 4601 4602 if ( tmp ) { 4603 elem[ ontype ] = null; 4604 } 4605 4606 // Prevent re-triggering of the same event, since we already bubbled it above 4607 jQuery.event.triggered = type; 4608 try { 4609 elem[ type ](); 4610 } catch ( e ) { 4611 // IE<9 dies on focus/blur to hidden element (#1486,#12518) 4612 // only reproducible on winXP IE8 native, not IE9 in IE8 mode 4613 } 4614 jQuery.event.triggered = undefined; 4615 4616 if ( tmp ) { 4617 elem[ ontype ] = tmp; 4618 } 4619 } 4620 } 4621 } 4622 4623 return event.result; 4624 }, 4625 4626 dispatch: function( event ) { 4627 4628 // Make a writable jQuery.Event from the native event object 4629 event = jQuery.event.fix( event ); 4630 4631 var i, ret, handleObj, matched, j, 4632 handlerQueue = [], 4633 args = slice.call( arguments ), 4634 handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], 4635 special = jQuery.event.special[ event.type ] || {}; 4636 4637 // Use the fix-ed jQuery.Event rather than the (read-only) native event 4638 args[0] = event; 4639 event.delegateTarget = this; 4640 4641 // Call the preDispatch hook for the mapped type, and let it bail if desired 4642 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { 4643 return; 4644 } 4645 4646 // Determine handlers 4647 handlerQueue = jQuery.event.handlers.call( this, event, handlers ); 4648 4649 // Run delegates first; they may want to stop propagation beneath us 4650 i = 0; 4651 while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { 4652 event.currentTarget = matched.elem; 4653 4654 j = 0; 4655 while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { 4656 4657 // Triggered event must either 1) have no namespace, or 4658 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). 4659 if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { 4660 4661 event.handleObj = handleObj; 4662 event.data = handleObj.data; 4663 4664 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) 4665 .apply( matched.elem, args ); 4666 4667 if ( ret !== undefined ) { 4668 if ( (event.result = ret) === false ) { 4669 event.preventDefault(); 4670 event.stopPropagation(); 4671 } 4672 } 4673 } 4674 } 4675 } 4676 4677 // Call the postDispatch hook for the mapped type 4678 if ( special.postDispatch ) { 4679 special.postDispatch.call( this, event ); 4680 } 4681 4682 return event.result; 4683 }, 4684 4685 handlers: function( event, handlers ) { 4686 var sel, handleObj, matches, i, 4687 handlerQueue = [], 4688 delegateCount = handlers.delegateCount, 4689 cur = event.target; 4690 4691 // Find delegate handlers 4692 // Black-hole SVG <use> instance trees (#13180) 4693 // Avoid non-left-click bubbling in Firefox (#3861) 4694 if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { 4695 4696 /* jshint eqeqeq: false */ 4697 for ( ; cur != this; cur = cur.parentNode || this ) { 4698 /* jshint eqeqeq: true */ 4699 4700 // Don't check non-elements (#13208) 4701 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) 4702 if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { 4703 matches = []; 4704 for ( i = 0; i < delegateCount; i++ ) { 4705 handleObj = handlers[ i ]; 4706 4707 // Don't conflict with Object.prototype properties (#13203) 4708 sel = handleObj.selector + " "; 4709 4710 if ( matches[ sel ] === undefined ) { 4711 matches[ sel ] = handleObj.needsContext ? 4712 jQuery( sel, this ).index( cur ) >= 0 : 4713 jQuery.find( sel, this, null, [ cur ] ).length; 4714 } 4715 if ( matches[ sel ] ) { 4716 matches.push( handleObj ); 4717 } 4718 } 4719 if ( matches.length ) { 4720 handlerQueue.push({ elem: cur, handlers: matches }); 4721 } 4722 } 4723 } 4724 } 4725 4726 // Add the remaining (directly-bound) handlers 4727 if ( delegateCount < handlers.length ) { 4728 handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); 4729 } 4730 4731 return handlerQueue; 4732 }, 4733 4734 fix: function( event ) { 4735 if ( event[ jQuery.expando ] ) { 4736 return event; 4737 } 4738 4739 // Create a writable copy of the event object and normalize some properties 4740 var i, prop, copy, 4741 type = event.type, 4742 originalEvent = event, 4743 fixHook = this.fixHooks[ type ]; 4744 4745 if ( !fixHook ) { 4746 this.fixHooks[ type ] = fixHook = 4747 rmouseEvent.test( type ) ? this.mouseHooks : 4748 rkeyEvent.test( type ) ? this.keyHooks : 4749 {}; 4750 } 4751 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; 4752 4753 event = new jQuery.Event( originalEvent ); 4754 4755 i = copy.length; 4756 while ( i-- ) { 4757 prop = copy[ i ]; 4758 event[ prop ] = originalEvent[ prop ]; 4759 } 4760 4761 // Support: IE<9 4762 // Fix target property (#1925) 4763 if ( !event.target ) { 4764 event.target = originalEvent.srcElement || document; 4765 } 4766 4767 // Support: Chrome 23+, Safari? 4768 // Target should not be a text node (#504, #13143) 4769 if ( event.target.nodeType === 3 ) { 4770 event.target = event.target.parentNode; 4771 } 4772 4773 // Support: IE<9 4774 // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) 4775 event.metaKey = !!event.metaKey; 4776 4777 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; 4778 }, 4779 4780 // Includes some event props shared by KeyEvent and MouseEvent 4781 props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), 4782 4783 fixHooks: {}, 4784 4785 keyHooks: { 4786 props: "char charCode key keyCode".split(" "), 4787 filter: function( event, original ) { 4788 4789 // Add which for key events 4790 if ( event.which == null ) { 4791 event.which = original.charCode != null ? original.charCode : original.keyCode; 4792 } 4793 4794 return event; 4795 } 4796 }, 4797 4798 mouseHooks: { 4799 props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), 4800 filter: function( event, original ) { 4801 var body, eventDoc, doc, 4802 button = original.button, 4803 fromElement = original.fromElement; 4804 4805 // Calculate pageX/Y if missing and clientX/Y available 4806 if ( event.pageX == null && original.clientX != null ) { 4807 eventDoc = event.target.ownerDocument || document; 4808 doc = eventDoc.documentElement; 4809 body = eventDoc.body; 4810 4811 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); 4812 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); 4813 } 4814 4815 // Add relatedTarget, if necessary 4816 if ( !event.relatedTarget && fromElement ) { 4817 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; 4818 } 4819 4820 // Add which for click: 1 === left; 2 === middle; 3 === right 4821 // Note: button is not normalized, so don't use it 4822 if ( !event.which && button !== undefined ) { 4823 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); 4824 } 4825 4826 return event; 4827 } 4828 }, 4829 4830 special: { 4831 load: { 4832 // Prevent triggered image.load events from bubbling to window.load 4833 noBubble: true 4834 }, 4835 focus: { 4836 // Fire native event if possible so blur/focus sequence is correct 4837 trigger: function() { 4838 if ( this !== safeActiveElement() && this.focus ) { 4839 try { 4840 this.focus(); 4841 return false; 4842 } catch ( e ) { 4843 // Support: IE<9 4844 // If we error on focus to hidden element (#1486, #12518), 4845 // let .trigger() run the handlers 4846 } 4847 } 4848 }, 4849 delegateType: "focusin" 4850 }, 4851 blur: { 4852 trigger: function() { 4853 if ( this === safeActiveElement() && this.blur ) { 4854 this.blur(); 4855 return false; 4856 } 4857 }, 4858 delegateType: "focusout" 4859 }, 4860 click: { 4861 // For checkbox, fire native event so checked state will be right 4862 trigger: function() { 4863 if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { 4864 this.click(); 4865 return false; 4866 } 4867 }, 4868 4869 // For cross-browser consistency, don't fire native .click() on links 4870 _default: function( event ) { 4871 return jQuery.nodeName( event.target, "a" ); 4872 } 4873 }, 4874 4875 beforeunload: { 4876 postDispatch: function( event ) { 4877 4878 // Support: Firefox 20+ 4879 // Firefox doesn't alert if the returnValue field is not set. 4880 if ( event.result !== undefined && event.originalEvent ) { 4881 event.originalEvent.returnValue = event.result; 4882 } 4883 } 4884 } 4885 }, 4886 4887 simulate: function( type, elem, event, bubble ) { 4888 // Piggyback on a donor event to simulate a different one. 4889 // Fake originalEvent to avoid donor's stopPropagation, but if the 4890 // simulated event prevents default then we do the same on the donor. 4891 var e = jQuery.extend( 4892 new jQuery.Event(), 4893 event, 4894 { 4895 type: type, 4896 isSimulated: true, 4897 originalEvent: {} 4898 } 4899 ); 4900 if ( bubble ) { 4901 jQuery.event.trigger( e, null, elem ); 4902 } else { 4903 jQuery.event.dispatch.call( elem, e ); 4904 } 4905 if ( e.isDefaultPrevented() ) { 4906 event.preventDefault(); 4907 } 4908 } 4909}; 4910 4911jQuery.removeEvent = document.removeEventListener ? 4912 function( elem, type, handle ) { 4913 if ( elem.removeEventListener ) { 4914 elem.removeEventListener( type, handle, false ); 4915 } 4916 } : 4917 function( elem, type, handle ) { 4918 var name = "on" + type; 4919 4920 if ( elem.detachEvent ) { 4921 4922 // #8545, #7054, preventing memory leaks for custom events in IE6-8 4923 // detachEvent needed property on element, by name of that event, to properly expose it to GC 4924 if ( typeof elem[ name ] === strundefined ) { 4925 elem[ name ] = null; 4926 } 4927 4928 elem.detachEvent( name, handle ); 4929 } 4930 }; 4931 4932jQuery.Event = function( src, props ) { 4933 // Allow instantiation without the 'new' keyword 4934 if ( !(this instanceof jQuery.Event) ) { 4935 return new jQuery.Event( src, props ); 4936 } 4937 4938 // Event object 4939 if ( src && src.type ) { 4940 this.originalEvent = src; 4941 this.type = src.type; 4942 4943 // Events bubbling up the document may have been marked as prevented 4944 // by a handler lower down the tree; reflect the correct value. 4945 this.isDefaultPrevented = src.defaultPrevented || 4946 src.defaultPrevented === undefined && 4947 // Support: IE < 9, Android < 4.0 4948 src.returnValue === false ? 4949 returnTrue : 4950 returnFalse; 4951 4952 // Event type 4953 } else { 4954 this.type = src; 4955 } 4956 4957 // Put explicitly provided properties onto the event object 4958 if ( props ) { 4959 jQuery.extend( this, props ); 4960 } 4961 4962 // Create a timestamp if incoming event doesn't have one 4963 this.timeStamp = src && src.timeStamp || jQuery.now(); 4964 4965 // Mark it as fixed 4966 this[ jQuery.expando ] = true; 4967}; 4968 4969// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding 4970// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 4971jQuery.Event.prototype = { 4972 isDefaultPrevented: returnFalse, 4973 isPropagationStopped: returnFalse, 4974 isImmediatePropagationStopped: returnFalse, 4975 4976 preventDefault: function() { 4977 var e = this.originalEvent; 4978 4979 this.isDefaultPrevented = returnTrue; 4980 if ( !e ) { 4981 return; 4982 } 4983 4984 // If preventDefault exists, run it on the original event 4985 if ( e.preventDefault ) { 4986 e.preventDefault(); 4987 4988 // Support: IE 4989 // Otherwise set the returnValue property of the original event to false 4990 } else { 4991 e.returnValue = false; 4992 } 4993 }, 4994 stopPropagation: function() { 4995 var e = this.originalEvent; 4996 4997 this.isPropagationStopped = returnTrue; 4998 if ( !e ) { 4999 return; 5000 } 5001 // If stopPropagation exists, run it on the original event 5002 if ( e.stopPropagation ) { 5003 e.stopPropagation(); 5004 } 5005 5006 // Support: IE 5007 // Set the cancelBubble property of the original event to true 5008 e.cancelBubble = true; 5009 }, 5010 stopImmediatePropagation: function() { 5011 var e = this.originalEvent; 5012 5013 this.isImmediatePropagationStopped = returnTrue; 5014 5015 if ( e && e.stopImmediatePropagation ) { 5016 e.stopImmediatePropagation(); 5017 } 5018 5019 this.stopPropagation(); 5020 } 5021}; 5022 5023// Create mouseenter/leave events using mouseover/out and event-time checks 5024jQuery.each({ 5025 mouseenter: "mouseover", 5026 mouseleave: "mouseout", 5027 pointerenter: "pointerover", 5028 pointerleave: "pointerout" 5029}, function( orig, fix ) { 5030 jQuery.event.special[ orig ] = { 5031 delegateType: fix, 5032 bindType: fix, 5033 5034 handle: function( event ) { 5035 var ret, 5036 target = this, 5037 related = event.relatedTarget, 5038 handleObj = event.handleObj; 5039 5040 // For mousenter/leave call the handler if related is outside the target. 5041 // NB: No relatedTarget if the mouse left/entered the browser window 5042 if ( !related || (related !== target && !jQuery.contains( target, related )) ) { 5043 event.type = handleObj.origType; 5044 ret = handleObj.handler.apply( this, arguments ); 5045 event.type = fix; 5046 } 5047 return ret; 5048 } 5049 }; 5050}); 5051 5052// IE submit delegation 5053if ( !support.submitBubbles ) { 5054 5055 jQuery.event.special.submit = { 5056 setup: function() { 5057 // Only need this for delegated form submit events 5058 if ( jQuery.nodeName( this, "form" ) ) { 5059 return false; 5060 } 5061 5062 // Lazy-add a submit handler when a descendant form may potentially be submitted 5063 jQuery.event.add( this, "click._submit keypress._submit", function( e ) { 5064 // Node name check avoids a VML-related crash in IE (#9807) 5065 var elem = e.target, 5066 form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; 5067 if ( form && !jQuery._data( form, "submitBubbles" ) ) { 5068 jQuery.event.add( form, "submit._submit", function( event ) { 5069 event._submit_bubble = true; 5070 }); 5071 jQuery._data( form, "submitBubbles", true ); 5072 } 5073 }); 5074 // return undefined since we don't need an event listener 5075 }, 5076 5077 postDispatch: function( event ) { 5078 // If form was submitted by the user, bubble the event up the tree 5079 if ( event._submit_bubble ) { 5080 delete event._submit_bubble; 5081 if ( this.parentNode && !event.isTrigger ) { 5082 jQuery.event.simulate( "submit", this.parentNode, event, true ); 5083 } 5084 } 5085 }, 5086 5087 teardown: function() { 5088 // Only need this for delegated form submit events 5089 if ( jQuery.nodeName( this, "form" ) ) { 5090 return false; 5091 } 5092 5093 // Remove delegated handlers; cleanData eventually reaps submit handlers attached above 5094 jQuery.event.remove( this, "._submit" ); 5095 } 5096 }; 5097} 5098 5099// IE change delegation and checkbox/radio fix 5100if ( !support.changeBubbles ) { 5101 5102 jQuery.event.special.change = { 5103 5104 setup: function() { 5105 5106 if ( rformElems.test( this.nodeName ) ) { 5107 // IE doesn't fire change on a check/radio until blur; trigger it on click 5108 // after a propertychange. Eat the blur-change in special.change.handle. 5109 // This still fires onchange a second time for check/radio after blur. 5110 if ( this.type === "checkbox" || this.type === "radio" ) { 5111 jQuery.event.add( this, "propertychange._change", function( event ) { 5112 if ( event.originalEvent.propertyName === "checked" ) { 5113 this._just_changed = true; 5114 } 5115 }); 5116 jQuery.event.add( this, "click._change", function( event ) { 5117 if ( this._just_changed && !event.isTrigger ) { 5118 this._just_changed = false; 5119 } 5120 // Allow triggered, simulated change events (#11500) 5121 jQuery.event.simulate( "change", this, event, true ); 5122 }); 5123 } 5124 return false; 5125 } 5126 // Delegated event; lazy-add a change handler on descendant inputs 5127 jQuery.event.add( this, "beforeactivate._change", function( e ) { 5128 var elem = e.target; 5129 5130 if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { 5131 jQuery.event.add( elem, "change._change", function( event ) { 5132 if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { 5133 jQuery.event.simulate( "change", this.parentNode, event, true ); 5134 } 5135 }); 5136 jQuery._data( elem, "changeBubbles", true ); 5137 } 5138 }); 5139 }, 5140 5141 handle: function( event ) { 5142 var elem = event.target; 5143 5144 // Swallow native change events from checkbox/radio, we already triggered them above 5145 if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { 5146 return event.handleObj.handler.apply( this, arguments ); 5147 } 5148 }, 5149 5150 teardown: function() { 5151 jQuery.event.remove( this, "._change" ); 5152 5153 return !rformElems.test( this.nodeName ); 5154 } 5155 }; 5156} 5157 5158// Create "bubbling" focus and blur events 5159if ( !support.focusinBubbles ) { 5160 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { 5161 5162 // Attach a single capturing handler on the document while someone wants focusin/focusout 5163 var handler = function( event ) { 5164 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); 5165 }; 5166 5167 jQuery.event.special[ fix ] = { 5168 setup: function() { 5169 var doc = this.ownerDocument || this, 5170 attaches = jQuery._data( doc, fix ); 5171 5172 if ( !attaches ) { 5173 doc.addEventListener( orig, handler, true ); 5174 } 5175 jQuery._data( doc, fix, ( attaches || 0 ) + 1 ); 5176 }, 5177 teardown: function() { 5178 var doc = this.ownerDocument || this, 5179 attaches = jQuery._data( doc, fix ) - 1; 5180 5181 if ( !attaches ) { 5182 doc.removeEventListener( orig, handler, true ); 5183 jQuery._removeData( doc, fix ); 5184 } else { 5185 jQuery._data( doc, fix, attaches ); 5186 } 5187 } 5188 }; 5189 }); 5190} 5191 5192jQuery.fn.extend({ 5193 5194 on: function( types, selector, data, fn, /*INTERNAL*/ one ) { 5195 var type, origFn; 5196 5197 // Types can be a map of types/handlers 5198 if ( typeof types === "object" ) { 5199 // ( types-Object, selector, data ) 5200 if ( typeof selector !== "string" ) { 5201 // ( types-Object, data ) 5202 data = data || selector; 5203 selector = undefined; 5204 } 5205 for ( type in types ) { 5206 this.on( type, selector, data, types[ type ], one ); 5207 } 5208 return this; 5209 } 5210 5211 if ( data == null && fn == null ) { 5212 // ( types, fn ) 5213 fn = selector; 5214 data = selector = undefined; 5215 } else if ( fn == null ) { 5216 if ( typeof selector === "string" ) { 5217 // ( types, selector, fn ) 5218 fn = data; 5219 data = undefined; 5220 } else { 5221 // ( types, data, fn ) 5222 fn = data; 5223 data = selector; 5224 selector = undefined; 5225 } 5226 } 5227 if ( fn === false ) { 5228 fn = returnFalse; 5229 } else if ( !fn ) { 5230 return this; 5231 } 5232 5233 if ( one === 1 ) { 5234 origFn = fn; 5235 fn = function( event ) { 5236 // Can use an empty set, since event contains the info 5237 jQuery().off( event ); 5238 return origFn.apply( this, arguments ); 5239 }; 5240 // Use same guid so caller can remove using origFn 5241 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); 5242 } 5243 return this.each( function() { 5244 jQuery.event.add( this, types, fn, data, selector ); 5245 }); 5246 }, 5247 one: function( types, selector, data, fn ) { 5248 return this.on( types, selector, data, fn, 1 ); 5249 }, 5250 off: function( types, selector, fn ) { 5251 var handleObj, type; 5252 if ( types && types.preventDefault && types.handleObj ) { 5253 // ( event ) dispatched jQuery.Event 5254 handleObj = types.handleObj; 5255 jQuery( types.delegateTarget ).off( 5256 handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, 5257 handleObj.selector, 5258 handleObj.handler 5259 ); 5260 return this; 5261 } 5262 if ( typeof types === "object" ) { 5263 // ( types-object [, selector] ) 5264 for ( type in types ) { 5265 this.off( type, selector, types[ type ] ); 5266 } 5267 return this; 5268 } 5269 if ( selector === false || typeof selector === "function" ) { 5270 // ( types [, fn] ) 5271 fn = selector; 5272 selector = undefined; 5273 } 5274 if ( fn === false ) { 5275 fn = returnFalse; 5276 } 5277 return this.each(function() { 5278 jQuery.event.remove( this, types, fn, selector ); 5279 }); 5280 }, 5281 5282 trigger: function( type, data ) { 5283 return this.each(function() { 5284 jQuery.event.trigger( type, data, this ); 5285 }); 5286 }, 5287 triggerHandler: function( type, data ) { 5288 var elem = this[0]; 5289 if ( elem ) { 5290 return jQuery.event.trigger( type, data, elem, true ); 5291 } 5292 } 5293}); 5294 5295 5296function createSafeFragment( document ) { 5297 var list = nodeNames.split( "|" ), 5298 safeFrag = document.createDocumentFragment(); 5299 5300 if ( safeFrag.createElement ) { 5301 while ( list.length ) { 5302 safeFrag.createElement( 5303 list.pop() 5304 ); 5305 } 5306 } 5307 return safeFrag; 5308} 5309 5310var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + 5311 "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", 5312 rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, 5313 rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), 5314 rleadingWhitespace = /^\s+/, 5315 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, 5316 rtagName = /<([\w:]+)/, 5317 rtbody = /<tbody/i, 5318 rhtml = /<|&#?\w+;/, 5319 rnoInnerhtml = /<(?:script|style|link)/i, 5320 // checked="checked" or checked 5321 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, 5322 rscriptType = /^$|\/(?:java|ecma)script/i, 5323 rscriptTypeMasked = /^true\/(.*)/, 5324 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, 5325 5326 // We have to close these tags to support XHTML (#13200) 5327 wrapMap = { 5328 option: [ 1, "<select multiple='multiple'>", "</select>" ], 5329 legend: [ 1, "<fieldset>", "</fieldset>" ], 5330 area: [ 1, "<map>", "</map>" ], 5331 param: [ 1, "<object>", "</object>" ], 5332 thead: [ 1, "<table>", "</table>" ], 5333 tr: [ 2, "<table><tbody>", "</tbody></table>" ], 5334 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ], 5335 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], 5336 5337 // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, 5338 // unless wrapped in a div with non-breaking characters in front of it. 5339 _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ] 5340 }, 5341 safeFragment = createSafeFragment( document ), 5342 fragmentDiv = safeFragment.appendChild( document.createElement("div") ); 5343 5344wrapMap.optgroup = wrapMap.option; 5345wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; 5346wrapMap.th = wrapMap.td; 5347 5348function getAll( context, tag ) { 5349 var elems, elem, 5350 i = 0, 5351 found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) : 5352 typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) : 5353 undefined; 5354 5355 if ( !found ) { 5356 for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { 5357 if ( !tag || jQuery.nodeName( elem, tag ) ) { 5358 found.push( elem ); 5359 } else { 5360 jQuery.merge( found, getAll( elem, tag ) ); 5361 } 5362 } 5363 } 5364 5365 return tag === undefined || tag && jQuery.nodeName( context, tag ) ? 5366 jQuery.merge( [ context ], found ) : 5367 found; 5368} 5369 5370// Used in buildFragment, fixes the defaultChecked property 5371function fixDefaultChecked( elem ) { 5372 if ( rcheckableType.test( elem.type ) ) { 5373 elem.defaultChecked = elem.checked; 5374 } 5375} 5376 5377// Support: IE<8 5378// Manipulating tables requires a tbody 5379function manipulationTarget( elem, content ) { 5380 return jQuery.nodeName( elem, "table" ) && 5381 jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? 5382 5383 elem.getElementsByTagName("tbody")[0] || 5384 elem.appendChild( elem.ownerDocument.createElement("tbody") ) : 5385 elem; 5386} 5387 5388// Replace/restore the type attribute of script elements for safe DOM manipulation 5389function disableScript( elem ) { 5390 elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; 5391 return elem; 5392} 5393function restoreScript( elem ) { 5394 var match = rscriptTypeMasked.exec( elem.type ); 5395 if ( match ) { 5396 elem.type = match[1]; 5397 } else { 5398 elem.removeAttribute("type"); 5399 } 5400 return elem; 5401} 5402 5403// Mark scripts as having already been evaluated 5404function setGlobalEval( elems, refElements ) { 5405 var elem, 5406 i = 0; 5407 for ( ; (elem = elems[i]) != null; i++ ) { 5408 jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); 5409 } 5410} 5411 5412function cloneCopyEvent( src, dest ) { 5413 5414 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { 5415 return; 5416 } 5417 5418 var type, i, l, 5419 oldData = jQuery._data( src ), 5420 curData = jQuery._data( dest, oldData ), 5421 events = oldData.events; 5422 5423 if ( events ) { 5424 delete curData.handle; 5425 curData.events = {}; 5426 5427 for ( type in events ) { 5428 for ( i = 0, l = events[ type ].length; i < l; i++ ) { 5429 jQuery.event.add( dest, type, events[ type ][ i ] ); 5430 } 5431 } 5432 } 5433 5434 // make the cloned public data object a copy from the original 5435 if ( curData.data ) { 5436 curData.data = jQuery.extend( {}, curData.data ); 5437 } 5438} 5439 5440function fixCloneNodeIssues( src, dest ) { 5441 var nodeName, e, data; 5442 5443 // We do not need to do anything for non-Elements 5444 if ( dest.nodeType !== 1 ) { 5445 return; 5446 } 5447 5448 nodeName = dest.nodeName.toLowerCase(); 5449 5450 // IE6-8 copies events bound via attachEvent when using cloneNode. 5451 if ( !support.noCloneEvent && dest[ jQuery.expando ] ) { 5452 data = jQuery._data( dest ); 5453 5454 for ( e in data.events ) { 5455 jQuery.removeEvent( dest, e, data.handle ); 5456 } 5457 5458 // Event data gets referenced instead of copied if the expando gets copied too 5459 dest.removeAttribute( jQuery.expando ); 5460 } 5461 5462 // IE blanks contents when cloning scripts, and tries to evaluate newly-set text 5463 if ( nodeName === "script" && dest.text !== src.text ) { 5464 disableScript( dest ).text = src.text; 5465 restoreScript( dest ); 5466 5467 // IE6-10 improperly clones children of object elements using classid. 5468 // IE10 throws NoModificationAllowedError if parent is null, #12132. 5469 } else if ( nodeName === "object" ) { 5470 if ( dest.parentNode ) { 5471 dest.outerHTML = src.outerHTML; 5472 } 5473 5474 // This path appears unavoidable for IE9. When cloning an object 5475 // element in IE9, the outerHTML strategy above is not sufficient. 5476 // If the src has innerHTML and the destination does not, 5477 // copy the src.innerHTML into the dest.innerHTML. #10324 5478 if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { 5479 dest.innerHTML = src.innerHTML; 5480 } 5481 5482 } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { 5483 // IE6-8 fails to persist the checked state of a cloned checkbox 5484 // or radio button. Worse, IE6-7 fail to give the cloned element 5485 // a checked appearance if the defaultChecked value isn't also set 5486 5487 dest.defaultChecked = dest.checked = src.checked; 5488 5489 // IE6-7 get confused and end up setting the value of a cloned 5490 // checkbox/radio button to an empty string instead of "on" 5491 if ( dest.value !== src.value ) { 5492 dest.value = src.value; 5493 } 5494 5495 // IE6-8 fails to return the selected option to the default selected 5496 // state when cloning options 5497 } else if ( nodeName === "option" ) { 5498 dest.defaultSelected = dest.selected = src.defaultSelected; 5499 5500 // IE6-8 fails to set the defaultValue to the correct value when 5501 // cloning other types of input fields 5502 } else if ( nodeName === "input" || nodeName === "textarea" ) { 5503 dest.defaultValue = src.defaultValue; 5504 } 5505} 5506 5507jQuery.extend({ 5508 clone: function( elem, dataAndEvents, deepDataAndEvents ) { 5509 var destElements, node, clone, i, srcElements, 5510 inPage = jQuery.contains( elem.ownerDocument, elem ); 5511 5512 if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { 5513 clone = elem.cloneNode( true ); 5514 5515 // IE<=8 does not properly clone detached, unknown element nodes 5516 } else { 5517 fragmentDiv.innerHTML = elem.outerHTML; 5518 fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); 5519 } 5520 5521 if ( (!support.noCloneEvent || !support.noCloneChecked) && 5522 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { 5523 5524 // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 5525 destElements = getAll( clone ); 5526 srcElements = getAll( elem ); 5527 5528 // Fix all IE cloning issues 5529 for ( i = 0; (node = srcElements[i]) != null; ++i ) { 5530 // Ensure that the destination node is not null; Fixes #9587 5531 if ( destElements[i] ) { 5532 fixCloneNodeIssues( node, destElements[i] ); 5533 } 5534 } 5535 } 5536 5537 // Copy the events from the original to the clone 5538 if ( dataAndEvents ) { 5539 if ( deepDataAndEvents ) { 5540 srcElements = srcElements || getAll( elem ); 5541 destElements = destElements || getAll( clone ); 5542 5543 for ( i = 0; (node = srcElements[i]) != null; i++ ) { 5544 cloneCopyEvent( node, destElements[i] ); 5545 } 5546 } else { 5547 cloneCopyEvent( elem, clone ); 5548 } 5549 } 5550 5551 // Preserve script evaluation history 5552 destElements = getAll( clone, "script" ); 5553 if ( destElements.length > 0 ) { 5554 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); 5555 } 5556 5557 destElements = srcElements = node = null; 5558 5559 // Return the cloned set 5560 return clone; 5561 }, 5562 5563 buildFragment: function( elems, context, scripts, selection ) { 5564 var j, elem, contains, 5565 tmp, tag, tbody, wrap, 5566 l = elems.length, 5567 5568 // Ensure a safe fragment 5569 safe = createSafeFragment( context ), 5570 5571 nodes = [], 5572 i = 0; 5573 5574 for ( ; i < l; i++ ) { 5575 elem = elems[ i ]; 5576 5577 if ( elem || elem === 0 ) { 5578 5579 // Add nodes directly 5580 if ( jQuery.type( elem ) === "object" ) { 5581 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); 5582 5583 // Convert non-html into a text node 5584 } else if ( !rhtml.test( elem ) ) { 5585 nodes.push( context.createTextNode( elem ) ); 5586 5587 // Convert html into DOM nodes 5588 } else { 5589 tmp = tmp || safe.appendChild( context.createElement("div") ); 5590 5591 // Deserialize a standard representation 5592 tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase(); 5593 wrap = wrapMap[ tag ] || wrapMap._default; 5594 5595 tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2]; 5596 5597 // Descend through wrappers to the right content 5598 j = wrap[0]; 5599 while ( j-- ) { 5600 tmp = tmp.lastChild; 5601 } 5602 5603 // Manually add leading whitespace removed by IE 5604 if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { 5605 nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); 5606 } 5607 5608 // Remove IE's autoinserted <tbody> from table fragments 5609 if ( !support.tbody ) { 5610 5611 // String was a <table>, *may* have spurious <tbody> 5612 elem = tag === "table" && !rtbody.test( elem ) ? 5613 tmp.firstChild : 5614 5615 // String was a bare <thead> or <tfoot> 5616 wrap[1] === "<table>" && !rtbody.test( elem ) ? 5617 tmp : 5618 0; 5619 5620 j = elem && elem.childNodes.length; 5621 while ( j-- ) { 5622 if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { 5623 elem.removeChild( tbody ); 5624 } 5625 } 5626 } 5627 5628 jQuery.merge( nodes, tmp.childNodes ); 5629 5630 // Fix #12392 for WebKit and IE > 9 5631 tmp.textContent = ""; 5632 5633 // Fix #12392 for oldIE 5634 while ( tmp.firstChild ) { 5635 tmp.removeChild( tmp.firstChild ); 5636 } 5637 5638 // Remember the top-level container for proper cleanup 5639 tmp = safe.lastChild; 5640 } 5641 } 5642 } 5643 5644 // Fix #11356: Clear elements from fragment 5645 if ( tmp ) { 5646 safe.removeChild( tmp ); 5647 } 5648 5649 // Reset defaultChecked for any radios and checkboxes 5650 // about to be appended to the DOM in IE 6/7 (#8060) 5651 if ( !support.appendChecked ) { 5652 jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); 5653 } 5654 5655 i = 0; 5656 while ( (elem = nodes[ i++ ]) ) { 5657 5658 // #4087 - If origin and destination elements are the same, and this is 5659 // that element, do not do anything 5660 if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { 5661 continue; 5662 } 5663 5664 contains = jQuery.contains( elem.ownerDocument, elem ); 5665 5666 // Append to fragment 5667 tmp = getAll( safe.appendChild( elem ), "script" ); 5668 5669 // Preserve script evaluation history 5670 if ( contains ) { 5671 setGlobalEval( tmp ); 5672 } 5673 5674 // Capture executables 5675 if ( scripts ) { 5676 j = 0; 5677 while ( (elem = tmp[ j++ ]) ) { 5678 if ( rscriptType.test( elem.type || "" ) ) { 5679 scripts.push( elem ); 5680 } 5681 } 5682 } 5683 } 5684 5685 tmp = null; 5686 5687 return safe; 5688 }, 5689 5690 cleanData: function( elems, /* internal */ acceptData ) { 5691 var elem, type, id, data, 5692 i = 0, 5693 internalKey = jQuery.expando, 5694 cache = jQuery.cache, 5695 deleteExpando = support.deleteExpando, 5696 special = jQuery.event.special; 5697 5698 for ( ; (elem = elems[i]) != null; i++ ) { 5699 if ( acceptData || jQuery.acceptData( elem ) ) { 5700 5701 id = elem[ internalKey ]; 5702 data = id && cache[ id ]; 5703 5704 if ( data ) { 5705 if ( data.events ) { 5706 for ( type in data.events ) { 5707 if ( special[ type ] ) { 5708 jQuery.event.remove( elem, type ); 5709 5710 // This is a shortcut to avoid jQuery.event.remove's overhead 5711 } else { 5712 jQuery.removeEvent( elem, type, data.handle ); 5713 } 5714 } 5715 } 5716 5717 // Remove cache only if it was not already removed by jQuery.event.remove 5718 if ( cache[ id ] ) { 5719 5720 delete cache[ id ]; 5721 5722 // IE does not allow us to delete expando properties from nodes, 5723 // nor does it have a removeAttribute function on Document nodes; 5724 // we must handle all of these cases 5725 if ( deleteExpando ) { 5726 delete elem[ internalKey ]; 5727 5728 } else if ( typeof elem.removeAttribute !== strundefined ) { 5729 elem.removeAttribute( internalKey ); 5730 5731 } else { 5732 elem[ internalKey ] = null; 5733 } 5734 5735 deletedIds.push( id ); 5736 } 5737 } 5738 } 5739 } 5740 } 5741}); 5742 5743jQuery.fn.extend({ 5744 text: function( value ) { 5745 return access( this, function( value ) { 5746 return value === undefined ? 5747 jQuery.text( this ) : 5748 this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); 5749 }, null, value, arguments.length ); 5750 }, 5751 5752 append: function() { 5753 return this.domManip( arguments, function( elem ) { 5754 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 5755 var target = manipulationTarget( this, elem ); 5756 target.appendChild( elem ); 5757 } 5758 }); 5759 }, 5760 5761 prepend: function() { 5762 return this.domManip( arguments, function( elem ) { 5763 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 5764 var target = manipulationTarget( this, elem ); 5765 target.insertBefore( elem, target.firstChild ); 5766 } 5767 }); 5768 }, 5769 5770 before: function() { 5771 return this.domManip( arguments, function( elem ) { 5772 if ( this.parentNode ) { 5773 this.parentNode.insertBefore( elem, this ); 5774 } 5775 }); 5776 }, 5777 5778 after: function() { 5779 return this.domManip( arguments, function( elem ) { 5780 if ( this.parentNode ) { 5781 this.parentNode.insertBefore( elem, this.nextSibling ); 5782 } 5783 }); 5784 }, 5785 5786 remove: function( selector, keepData /* Internal Use Only */ ) { 5787 var elem, 5788 elems = selector ? jQuery.filter( selector, this ) : this, 5789 i = 0; 5790 5791 for ( ; (elem = elems[i]) != null; i++ ) { 5792 5793 if ( !keepData && elem.nodeType === 1 ) { 5794 jQuery.cleanData( getAll( elem ) ); 5795 } 5796 5797 if ( elem.parentNode ) { 5798 if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { 5799 setGlobalEval( getAll( elem, "script" ) ); 5800 } 5801 elem.parentNode.removeChild( elem ); 5802 } 5803 } 5804 5805 return this; 5806 }, 5807 5808 empty: function() { 5809 var elem, 5810 i = 0; 5811 5812 for ( ; (elem = this[i]) != null; i++ ) { 5813 // Remove element nodes and prevent memory leaks 5814 if ( elem.nodeType === 1 ) { 5815 jQuery.cleanData( getAll( elem, false ) ); 5816 } 5817 5818 // Remove any remaining nodes 5819 while ( elem.firstChild ) { 5820 elem.removeChild( elem.firstChild ); 5821 } 5822 5823 // If this is a select, ensure that it displays empty (#12336) 5824 // Support: IE<9 5825 if ( elem.options && jQuery.nodeName( elem, "select" ) ) { 5826 elem.options.length = 0; 5827 } 5828 } 5829 5830 return this; 5831 }, 5832 5833 clone: function( dataAndEvents, deepDataAndEvents ) { 5834 dataAndEvents = dataAndEvents == null ? false : dataAndEvents; 5835 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; 5836 5837 return this.map(function() { 5838 return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); 5839 }); 5840 }, 5841 5842 html: function( value ) { 5843 return access( this, function( value ) { 5844 var elem = this[ 0 ] || {}, 5845 i = 0, 5846 l = this.length; 5847 5848 if ( value === undefined ) { 5849 return elem.nodeType === 1 ? 5850 elem.innerHTML.replace( rinlinejQuery, "" ) : 5851 undefined; 5852 } 5853 5854 // See if we can take a shortcut and just use innerHTML 5855 if ( typeof value === "string" && !rnoInnerhtml.test( value ) && 5856 ( support.htmlSerialize || !rnoshimcache.test( value ) ) && 5857 ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && 5858 !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) { 5859 5860 value = value.replace( rxhtmlTag, "<$1></$2>" ); 5861 5862 try { 5863 for (; i < l; i++ ) { 5864 // Remove element nodes and prevent memory leaks 5865 elem = this[i] || {}; 5866 if ( elem.nodeType === 1 ) { 5867 jQuery.cleanData( getAll( elem, false ) ); 5868 elem.innerHTML = value; 5869 } 5870 } 5871 5872 elem = 0; 5873 5874 // If using innerHTML throws an exception, use the fallback method 5875 } catch(e) {} 5876 } 5877 5878 if ( elem ) { 5879 this.empty().append( value ); 5880 } 5881 }, null, value, arguments.length ); 5882 }, 5883 5884 replaceWith: function() { 5885 var arg = arguments[ 0 ]; 5886 5887 // Make the changes, replacing each context element with the new content 5888 this.domManip( arguments, function( elem ) { 5889 arg = this.parentNode; 5890 5891 jQuery.cleanData( getAll( this ) ); 5892 5893 if ( arg ) { 5894 arg.replaceChild( elem, this ); 5895 } 5896 }); 5897 5898 // Force removal if there was no new content (e.g., from empty arguments) 5899 return arg && (arg.length || arg.nodeType) ? this : this.remove(); 5900 }, 5901 5902 detach: function( selector ) { 5903 return this.remove( selector, true ); 5904 }, 5905 5906 domManip: function( args, callback ) { 5907 5908 // Flatten any nested arrays 5909 args = concat.apply( [], args ); 5910 5911 var first, node, hasScripts, 5912 scripts, doc, fragment, 5913 i = 0, 5914 l = this.length, 5915 set = this, 5916 iNoClone = l - 1, 5917 value = args[0], 5918 isFunction = jQuery.isFunction( value ); 5919 5920 // We can't cloneNode fragments that contain checked, in WebKit 5921 if ( isFunction || 5922 ( l > 1 && typeof value === "string" && 5923 !support.checkClone && rchecked.test( value ) ) ) { 5924 return this.each(function( index ) { 5925 var self = set.eq( index ); 5926 if ( isFunction ) { 5927 args[0] = value.call( this, index, self.html() ); 5928 } 5929 self.domManip( args, callback ); 5930 }); 5931 } 5932 5933 if ( l ) { 5934 fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); 5935 first = fragment.firstChild; 5936 5937 if ( fragment.childNodes.length === 1 ) { 5938 fragment = first; 5939 } 5940 5941 if ( first ) { 5942 scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); 5943 hasScripts = scripts.length; 5944 5945 // Use the original fragment for the last item instead of the first because it can end up 5946 // being emptied incorrectly in certain situations (#8070). 5947 for ( ; i < l; i++ ) { 5948 node = fragment; 5949 5950 if ( i !== iNoClone ) { 5951 node = jQuery.clone( node, true, true ); 5952 5953 // Keep references to cloned scripts for later restoration 5954 if ( hasScripts ) { 5955 jQuery.merge( scripts, getAll( node, "script" ) ); 5956 } 5957 } 5958 5959 callback.call( this[i], node, i ); 5960 } 5961 5962 if ( hasScripts ) { 5963 doc = scripts[ scripts.length - 1 ].ownerDocument; 5964 5965 // Reenable scripts 5966 jQuery.map( scripts, restoreScript ); 5967 5968 // Evaluate executable scripts on first document insertion 5969 for ( i = 0; i < hasScripts; i++ ) { 5970 node = scripts[ i ]; 5971 if ( rscriptType.test( node.type || "" ) && 5972 !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { 5973 5974 if ( node.src ) { 5975 // Optional AJAX dependency, but won't run scripts if not present 5976 if ( jQuery._evalUrl ) { 5977 jQuery._evalUrl( node.src ); 5978 } 5979 } else { 5980 jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); 5981 } 5982 } 5983 } 5984 } 5985 5986 // Fix #11809: Avoid leaking memory 5987 fragment = first = null; 5988 } 5989 } 5990 5991 return this; 5992 } 5993}); 5994 5995jQuery.each({ 5996 appendTo: "append", 5997 prependTo: "prepend", 5998 insertBefore: "before", 5999 insertAfter: "after", 6000 replaceAll: "replaceWith" 6001}, function( name, original ) { 6002 jQuery.fn[ name ] = function( selector ) { 6003 var elems, 6004 i = 0, 6005 ret = [], 6006 insert = jQuery( selector ), 6007 last = insert.length - 1; 6008 6009 for ( ; i <= last; i++ ) { 6010 elems = i === last ? this : this.clone(true); 6011 jQuery( insert[i] )[ original ]( elems ); 6012 6013 // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() 6014 push.apply( ret, elems.get() ); 6015 } 6016 6017 return this.pushStack( ret ); 6018 }; 6019}); 6020 6021 6022var iframe, 6023 elemdisplay = {}; 6024 6025/** 6026 * Retrieve the actual display of a element 6027 * @param {String} name nodeName of the element 6028 * @param {Object} doc Document object 6029 */ 6030// Called only from within defaultDisplay 6031function actualDisplay( name, doc ) { 6032 var style, 6033 elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), 6034 6035 // getDefaultComputedStyle might be reliably used only on attached element 6036 display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? 6037 6038 // Use of this method is a temporary fix (more like optmization) until something better comes along, 6039 // since it was removed from specification and supported only in FF 6040 style.display : jQuery.css( elem[ 0 ], "display" ); 6041 6042 // We don't have any data stored on the element, 6043 // so use "detach" method as fast way to get rid of the element 6044 elem.detach(); 6045 6046 return display; 6047} 6048 6049/** 6050 * Try to determine the default display value of an element 6051 * @param {String} nodeName 6052 */ 6053function defaultDisplay( nodeName ) { 6054 var doc = document, 6055 display = elemdisplay[ nodeName ]; 6056 6057 if ( !display ) { 6058 display = actualDisplay( nodeName, doc ); 6059 6060 // If the simple way fails, read from inside an iframe 6061 if ( display === "none" || !display ) { 6062 6063 // Use the already-created iframe if possible 6064 iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement ); 6065 6066 // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse 6067 doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document; 6068 6069 // Support: IE 6070 doc.write(); 6071 doc.close(); 6072 6073 display = actualDisplay( nodeName, doc ); 6074 iframe.detach(); 6075 } 6076 6077 // Store the correct default display 6078 elemdisplay[ nodeName ] = display; 6079 } 6080 6081 return display; 6082} 6083 6084 6085(function() { 6086 var shrinkWrapBlocksVal; 6087 6088 support.shrinkWrapBlocks = function() { 6089 if ( shrinkWrapBlocksVal != null ) { 6090 return shrinkWrapBlocksVal; 6091 } 6092 6093 // Will be changed later if needed. 6094 shrinkWrapBlocksVal = false; 6095 6096 // Minified: var b,c,d 6097 var div, body, container; 6098 6099 body = document.getElementsByTagName( "body" )[ 0 ]; 6100 if ( !body || !body.style ) { 6101 // Test fired too early or in an unsupported environment, exit. 6102 return; 6103 } 6104 6105 // Setup 6106 div = document.createElement( "div" ); 6107 container = document.createElement( "div" ); 6108 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; 6109 body.appendChild( container ).appendChild( div ); 6110 6111 // Support: IE6 6112 // Check if elements with layout shrink-wrap their children 6113 if ( typeof div.style.zoom !== strundefined ) { 6114 // Reset CSS: box-sizing; display; margin; border 6115 div.style.cssText = 6116 // Support: Firefox<29, Android 2.3 6117 // Vendor-prefix box-sizing 6118 "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + 6119 "box-sizing:content-box;display:block;margin:0;border:0;" + 6120 "padding:1px;width:1px;zoom:1"; 6121 div.appendChild( document.createElement( "div" ) ).style.width = "5px"; 6122 shrinkWrapBlocksVal = div.offsetWidth !== 3; 6123 } 6124 6125 body.removeChild( container ); 6126 6127 return shrinkWrapBlocksVal; 6128 }; 6129 6130})(); 6131var rmargin = (/^margin/); 6132 6133var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); 6134 6135 6136 6137var getStyles, curCSS, 6138 rposition = /^(top|right|bottom|left)$/; 6139 6140if ( window.getComputedStyle ) { 6141 getStyles = function( elem ) { 6142
6142// Support: IE<=11+, Firefox<=30+ (#15098, #14150) 6143 // IE throws on elements created in popups 6144 // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" 6145 if ( elem.ownerDocument.defaultView.opener ) { 6146 return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); 6147 } 6148 6149 return windo
vendor: 7,468 bytes, lines 6149-6396
6149w.getComputedStyle( elem, null ); 6150 }; 6151 6152 curCSS = function( elem, name, computed ) { 6153 var width, minWidth, maxWidth, ret, 6154 style = elem.style; 6155 6156 computed = computed || getStyles( elem ); 6157 6158 // getPropertyValue is only needed for .css('filter') in IE9, see #12537 6159 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined; 6160 6161 if ( computed ) { 6162 6163 if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { 6164 ret = jQuery.style( elem, name ); 6165 } 6166 6167 // A tribute to the "awesome hack by Dean Edwards" 6168 // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right 6169 // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels 6170 // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values 6171 if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { 6172 6173 // Remember the original values 6174 width = style.width; 6175 minWidth = style.minWidth; 6176 maxWidth = style.maxWidth; 6177 6178 // Put in the new values to get a computed value out 6179 style.minWidth = style.maxWidth = style.width = ret; 6180 ret = computed.width; 6181 6182 // Revert the changed values 6183 style.width = width; 6184 style.minWidth = minWidth; 6185 style.maxWidth = maxWidth; 6186 } 6187 } 6188 6189 // Support: IE 6190 // IE returns zIndex value as an integer. 6191 return ret === undefined ? 6192 ret : 6193 ret + ""; 6194 }; 6195} else if ( document.documentElement.currentStyle ) { 6196 getStyles = function( elem ) { 6197 return elem.currentStyle; 6198 }; 6199 6200 curCSS = function( elem, name, computed ) { 6201 var left, rs, rsLeft, ret, 6202 style = elem.style; 6203 6204 computed = computed || getStyles( elem ); 6205 ret = computed ? computed[ name ] : undefined; 6206 6207 // Avoid setting ret to empty string here 6208 // so we don't default to auto 6209 if ( ret == null && style && style[ name ] ) { 6210 ret = style[ name ]; 6211 } 6212 6213 // From the awesome hack by Dean Edwards 6214 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 6215 6216 // If we're not dealing with a regular pixel number 6217 // but a number that has a weird ending, we need to convert it to pixels 6218 // but not position css attributes, as those are proportional to the parent element instead 6219 // and we can't measure the parent instead because it might trigger a "stacking dolls" problem 6220 if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { 6221 6222 // Remember the original values 6223 left = style.left; 6224 rs = elem.runtimeStyle; 6225 rsLeft = rs && rs.left; 6226 6227 // Put in the new values to get a computed value out 6228 if ( rsLeft ) { 6229 rs.left = elem.currentStyle.left; 6230 } 6231 style.left = name === "fontSize" ? "1em" : ret; 6232 ret = style.pixelLeft + "px"; 6233 6234 // Revert the changed values 6235 style.left = left; 6236 if ( rsLeft ) { 6237 rs.left = rsLeft; 6238 } 6239 } 6240 6241 // Support: IE 6242 // IE returns zIndex value as an integer. 6243 return ret === undefined ? 6244 ret : 6245 ret + "" || "auto"; 6246 }; 6247} 6248 6249 6250 6251 6252function addGetHookIf( conditionFn, hookFn ) { 6253 // Define the hook, we'll check on the first run if it's really needed. 6254 return { 6255 get: function() { 6256 var condition = conditionFn(); 6257 6258 if ( condition == null ) { 6259 // The test was not ready at this point; screw the hook this time 6260 // but check again when needed next time. 6261 return; 6262 } 6263 6264 if ( condition ) { 6265 // Hook not needed (or it's not possible to use it due to missing dependency), 6266 // remove it. 6267 // Since there are no other hooks for marginRight, remove the whole object. 6268 delete this.get; 6269 return; 6270 } 6271 6272 // Hook needed; redefine it so that the support test is not executed again. 6273 6274 return (this.get = hookFn).apply( this, arguments ); 6275 } 6276 }; 6277} 6278 6279 6280(function() { 6281 // Minified: var b,c,d,e,f,g, h,i 6282 var div, style, a, pixelPositionVal, boxSizingReliableVal, 6283 reliableHiddenOffsetsVal, reliableMarginRightVal; 6284 6285 // Setup 6286 div = document.createElement( "div" ); 6287 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; 6288 a = div.getElementsByTagName( "a" )[ 0 ]; 6289 style = a && a.style; 6290 6291 // Finish early in limited (non-browser) environments 6292 if ( !style ) { 6293 return; 6294 } 6295 6296 style.cssText = "float:left;opacity:.5"; 6297 6298 // Support: IE<9 6299 // Make sure that element opacity exists (as opposed to filter) 6300 support.opacity = style.opacity === "0.5"; 6301 6302 // Verify style float existence 6303 // (IE uses styleFloat instead of cssFloat) 6304 support.cssFloat = !!style.cssFloat; 6305 6306 div.style.backgroundClip = "content-box"; 6307 div.cloneNode( true ).style.backgroundClip = ""; 6308 support.clearCloneStyle = div.style.backgroundClip === "content-box"; 6309 6310 // Support: Firefox<29, Android 2.3 6311 // Vendor-prefix box-sizing 6312 support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" || 6313 style.WebkitBoxSizing === ""; 6314 6315 jQuery.extend(support, { 6316 reliableHiddenOffsets: function() { 6317 if ( reliableHiddenOffsetsVal == null ) { 6318 computeStyleTests(); 6319 } 6320 return reliableHiddenOffsetsVal; 6321 }, 6322 6323 boxSizingReliable: function() { 6324 if ( boxSizingReliableVal == null ) { 6325 computeStyleTests(); 6326 } 6327 return boxSizingReliableVal; 6328 }, 6329 6330 pixelPosition: function() { 6331 if ( pixelPositionVal == null ) { 6332 computeStyleTests(); 6333 } 6334 return pixelPositionVal; 6335 }, 6336 6337 // Support: Android 2.3 6338 reliableMarginRight: function() { 6339 if ( reliableMarginRightVal == null ) { 6340 computeStyleTests(); 6341 } 6342 return reliableMarginRightVal; 6343 } 6344 }); 6345 6346 function computeStyleTests() { 6347 // Minified: var b,c,d,j 6348 var div, body, container, contents; 6349 6350 body = document.getElementsByTagName( "body" )[ 0 ]; 6351 if ( !body || !body.style ) { 6352 // Test fired too early or in an unsupported environment, exit. 6353 return; 6354 } 6355 6356 // Setup 6357 div = document.createElement( "div" ); 6358 container = document.createElement( "div" ); 6359 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; 6360 body.appendChild( container ).appendChild( div ); 6361 6362 div.style.cssText = 6363 // Support: Firefox<29, Android 2.3 6364 // Vendor-prefix box-sizing 6365 "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" + 6366 "box-sizing:border-box;display:block;margin-top:1%;top:1%;" + 6367 "border:1px;padding:1px;width:4px;position:absolute"; 6368 6369 // Support: IE<9 6370 // Assume reasonable values in the absence of getComputedStyle 6371 pixelPositionVal = boxSizingReliableVal = false; 6372 reliableMarginRightVal = true; 6373 6374 // Check for getComputedStyle so that this code is not run in IE<9. 6375 if ( window.getComputedStyle ) { 6376 pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; 6377 boxSizingReliableVal = 6378 ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; 6379 6380 // Support: Android 2.3 6381 // Div with explicit width and no margin-right incorrectly 6382 // gets computed margin-right based on width of container (#3333) 6383 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right 6384 contents = div.appendChild( document.createElement( "div" ) ); 6385 6386 // Reset CSS: box-sizing; display; margin; border; padding 6387 contents.style.cssText = div.style.cssText = 6388 // Support: Firefox<29, Android 2.3 6389 // Vendor-prefix box-sizing 6390 "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + 6391 "box-sizing:content-box;display:block;margin:0;border:0;padding:0"; 6392 contents.style.marginRight = contents.style.width = "0"; 6393 div.style.width = "1px"; 6394 6395 reliableMarginRightVal = 6396 !parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
6397 6398 div.removeChild( contents
vendor: 73,689 bytes, lines 6398-9106
6398 ); 6399 } 6400 6401 // Support: IE8 6402 // Check if table cells still have offsetWidth/Height when they are set 6403 // to display:none and there are still other visible table cells in a 6404 // table row; if so, offsetWidth/Height are not reliable for use when 6405 // determining if an element has been hidden directly using 6406 // display:none (it is still safe to use offsets if a parent element is 6407 // hidden; don safety goggles and see bug #4512 for more information). 6408 div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>"; 6409 contents = div.getElementsByTagName( "td" ); 6410 contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none"; 6411 reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0; 6412 if ( reliableHiddenOffsetsVal ) { 6413 contents[ 0 ].style.display = ""; 6414 contents[ 1 ].style.display = "none"; 6415 reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0; 6416 } 6417 6418 body.removeChild( container ); 6419 } 6420 6421})(); 6422 6423 6424// A method for quickly swapping in/out CSS properties to get correct calculations. 6425jQuery.swap = function( elem, options, callback, args ) { 6426 var ret, name, 6427 old = {}; 6428 6429 // Remember the old values, and insert the new ones 6430 for ( name in options ) { 6431 old[ name ] = elem.style[ name ]; 6432 elem.style[ name ] = options[ name ]; 6433 } 6434 6435 ret = callback.apply( elem, args || [] ); 6436 6437 // Revert the old values 6438 for ( name in options ) { 6439 elem.style[ name ] = old[ name ]; 6440 } 6441 6442 return ret; 6443}; 6444 6445 6446var 6447 ralpha = /alpha\([^)]*\)/i, 6448 ropacity = /opacity\s*=\s*([^)]*)/, 6449 6450 // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" 6451 // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display 6452 rdisplayswap = /^(none|table(?!-c[ea]).+)/, 6453 rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ), 6454 rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ), 6455 6456 cssShow = { position: "absolute", visibility: "hidden", display: "block" }, 6457 cssNormalTransform = { 6458 letterSpacing: "0", 6459 fontWeight: "400" 6460 }, 6461 6462 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; 6463 6464 6465// return a css property mapped to a potentially vendor prefixed property 6466function vendorPropName( style, name ) { 6467 6468 // shortcut for names that are not vendor prefixed 6469 if ( name in style ) { 6470 return name; 6471 } 6472 6473 // check for vendor prefixed names 6474 var capName = name.charAt(0).toUpperCase() + name.slice(1), 6475 origName = name, 6476 i = cssPrefixes.length; 6477 6478 while ( i-- ) { 6479 name = cssPrefixes[ i ] + capName; 6480 if ( name in style ) { 6481 return name; 6482 } 6483 } 6484 6485 return origName; 6486} 6487 6488function showHide( elements, show ) { 6489 var display, elem, hidden, 6490 values = [], 6491 index = 0, 6492 length = elements.length; 6493 6494 for ( ; index < length; index++ ) { 6495 elem = elements[ index ]; 6496 if ( !elem.style ) { 6497 continue; 6498 } 6499 6500 values[ index ] = jQuery._data( elem, "olddisplay" ); 6501 display = elem.style.display; 6502 if ( show ) { 6503 // Reset the inline display of this element to learn if it is 6504 // being hidden by cascaded rules or not 6505 if ( !values[ index ] && display === "none" ) { 6506 elem.style.display = ""; 6507 } 6508 6509 // Set elements which have been overridden with display: none 6510 // in a stylesheet to whatever the default browser style is 6511 // for such an element 6512 if ( elem.style.display === "" && isHidden( elem ) ) { 6513 values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) ); 6514 } 6515 } else { 6516 hidden = isHidden( elem ); 6517 6518 if ( display && display !== "none" || !hidden ) { 6519 jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); 6520 } 6521 } 6522 } 6523 6524 // Set the display of most of the elements in a second loop 6525 // to avoid the constant reflow 6526 for ( index = 0; index < length; index++ ) { 6527 elem = elements[ index ]; 6528 if ( !elem.style ) { 6529 continue; 6530 } 6531 if ( !show || elem.style.display === "none" || elem.style.display === "" ) { 6532 elem.style.display = show ? values[ index ] || "" : "none"; 6533 } 6534 } 6535 6536 return elements; 6537} 6538 6539function setPositiveNumber( elem, value, subtract ) { 6540 var matches = rnumsplit.exec( value ); 6541 return matches ? 6542 // Guard against undefined "subtract", e.g., when used as in cssHooks 6543 Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : 6544 value; 6545} 6546 6547function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { 6548 var i = extra === ( isBorderBox ? "border" : "content" ) ? 6549 // If we already have the right measurement, avoid augmentation 6550 4 : 6551 // Otherwise initialize for horizontal or vertical properties 6552 name === "width" ? 1 : 0, 6553 6554 val = 0; 6555 6556 for ( ; i < 4; i += 2 ) { 6557 // both box models exclude margin, so add it if we want it 6558 if ( extra === "margin" ) { 6559 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); 6560 } 6561 6562 if ( isBorderBox ) { 6563 // border-box includes padding, so remove it if we want content 6564 if ( extra === "content" ) { 6565 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 6566 } 6567 6568 // at this point, extra isn't border nor margin, so remove border 6569 if ( extra !== "margin" ) { 6570 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 6571 } 6572 } else { 6573 // at this point, extra isn't content, so add padding 6574 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 6575 6576 // at this point, extra isn't content nor padding, so add border 6577 if ( extra !== "padding" ) { 6578 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 6579 } 6580 } 6581 } 6582 6583 return val; 6584} 6585 6586function getWidthOrHeight( elem, name, extra ) { 6587 6588 // Start with offset property, which is equivalent to the border-box value 6589 var valueIsBorderBox = true, 6590 val = name === "width" ? elem.offsetWidth : elem.offsetHeight, 6591 styles = getStyles( elem ), 6592 isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; 6593 6594 // some non-html elements return undefined for offsetWidth, so check for null/undefined 6595 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 6596 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 6597 if ( val <= 0 || val == null ) { 6598 // Fall back to computed then uncomputed css if necessary 6599 val = curCSS( elem, name, styles ); 6600 if ( val < 0 || val == null ) { 6601 val = elem.style[ name ]; 6602 } 6603 6604 // Computed unit is not pixels. Stop here and return. 6605 if ( rnumnonpx.test(val) ) { 6606 return val; 6607 } 6608 6609 // we need the check for style in case a browser which returns unreliable values 6610 // for getComputedStyle silently falls back to the reliable elem.style 6611 valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] ); 6612 6613 // Normalize "", auto, and prepare for extra 6614 val = parseFloat( val ) || 0; 6615 } 6616 6617 // use the active box-sizing model to add/subtract irrelevant styles 6618 return ( val + 6619 augmentWidthOrHeight( 6620 elem, 6621 name, 6622 extra || ( isBorderBox ? "border" : "content" ), 6623 valueIsBorderBox, 6624 styles 6625 ) 6626 ) + "px"; 6627} 6628 6629jQuery.extend({ 6630 // Add in style property hooks for overriding the default 6631 // behavior of getting and setting a style property 6632 cssHooks: { 6633 opacity: { 6634 get: function( elem, computed ) { 6635 if ( computed ) { 6636 // We should always get a number back from opacity 6637 var ret = curCSS( elem, "opacity" ); 6638 return ret === "" ? "1" : ret; 6639 } 6640 } 6641 } 6642 }, 6643 6644 // Don't automatically add "px" to these possibly-unitless properties 6645 cssNumber: { 6646 "columnCount": true, 6647 "fillOpacity": true, 6648 "flexGrow": true, 6649 "flexShrink": true, 6650 "fontWeight": true, 6651 "lineHeight": true, 6652 "opacity": true, 6653 "order": true, 6654 "orphans": true, 6655 "widows": true, 6656 "zIndex": true, 6657 "zoom": true 6658 }, 6659 6660 // Add in properties whose names you wish to fix before 6661 // setting or getting the value 6662 cssProps: { 6663 // normalize float css property 6664 "float": support.cssFloat ? "cssFloat" : "styleFloat" 6665 }, 6666 6667 // Get and set the style property on a DOM Node 6668 style: function( elem, name, value, extra ) { 6669 // Don't set styles on text and comment nodes 6670 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { 6671 return; 6672 } 6673 6674 // Make sure that we're working with the right name 6675 var ret, type, hooks, 6676 origName = jQuery.camelCase( name ), 6677 style = elem.style; 6678 6679 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); 6680 6681 // gets hook for the prefixed version 6682 // followed by the unprefixed version 6683 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 6684 6685 // Check if we're setting a value 6686 if ( value !== undefined ) { 6687 type = typeof value; 6688 6689 // convert relative number strings (+= or -=) to relative numbers. #7345 6690 if ( type === "string" && (ret = rrelNum.exec( value )) ) { 6691 value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); 6692 // Fixes bug #9237 6693 type = "number"; 6694 } 6695 6696 // Make sure that null and NaN values aren't set. See: #7116 6697 if ( value == null || value !== value ) { 6698 return; 6699 } 6700 6701 // If a number was passed in, add 'px' to the (except for certain CSS properties) 6702 if ( type === "number" && !jQuery.cssNumber[ origName ] ) { 6703 value += "px"; 6704 } 6705 6706 // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, 6707 // but it would mean to define eight (for every problematic property) identical functions 6708 if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { 6709 style[ name ] = "inherit"; 6710 } 6711 6712 // If a hook was provided, use that value, otherwise just set the specified value 6713 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { 6714 6715 // Support: IE 6716 // Swallow errors from 'invalid' CSS values (#5509) 6717 try { 6718 style[ name ] = value; 6719 } catch(e) {} 6720 } 6721 6722 } else { 6723 // If a hook was provided get the non-computed value from there 6724 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { 6725 return ret; 6726 } 6727 6728 // Otherwise just get the value from the style object 6729 return style[ name ]; 6730 } 6731 }, 6732 6733 css: function( elem, name, extra, styles ) { 6734 var num, val, hooks, 6735 origName = jQuery.camelCase( name ); 6736 6737 // Make sure that we're working with the right name 6738 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); 6739 6740 // gets hook for the prefixed version 6741 // followed by the unprefixed version 6742 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 6743 6744 // If a hook was provided get the computed value from there 6745 if ( hooks && "get" in hooks ) { 6746 val = hooks.get( elem, true, extra ); 6747 } 6748 6749 // Otherwise, if a way to get the computed value exists, use that 6750 if ( val === undefined ) { 6751 val = curCSS( elem, name, styles ); 6752 } 6753 6754 //convert "normal" to computed value 6755 if ( val === "normal" && name in cssNormalTransform ) { 6756 val = cssNormalTransform[ name ]; 6757 } 6758 6759 // Return, converting to number if forced or a qualifier was provided and val looks numeric 6760 if ( extra === "" || extra ) { 6761 num = parseFloat( val ); 6762 return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; 6763 } 6764 return val; 6765 } 6766}); 6767 6768jQuery.each([ "height", "width" ], function( i, name ) { 6769 jQuery.cssHooks[ name ] = { 6770 get: function( elem, computed, extra ) { 6771 if ( computed ) { 6772 // certain elements can have dimension info if we invisibly show them 6773 // however, it must have a current display style that would benefit from this 6774 return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ? 6775 jQuery.swap( elem, cssShow, function() { 6776 return getWidthOrHeight( elem, name, extra ); 6777 }) : 6778 getWidthOrHeight( elem, name, extra ); 6779 } 6780 }, 6781 6782 set: function( elem, value, extra ) { 6783 var styles = extra && getStyles( elem ); 6784 return setPositiveNumber( elem, value, extra ? 6785 augmentWidthOrHeight( 6786 elem, 6787 name, 6788 extra, 6789 support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box", 6790 styles 6791 ) : 0 6792 ); 6793 } 6794 }; 6795}); 6796 6797if ( !support.opacity ) { 6798 jQuery.cssHooks.opacity = { 6799 get: function( elem, computed ) { 6800 // IE uses filters for opacity 6801 return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ? 6802 ( 0.01 * parseFloat( RegExp.$1 ) ) + "" : 6803 computed ? "1" : ""; 6804 }, 6805 6806 set: function( elem, value ) { 6807 var style = elem.style, 6808 currentStyle = elem.currentStyle, 6809 opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "", 6810 filter = currentStyle && currentStyle.filter || style.filter || ""; 6811 6812 // IE has trouble with opacity if it does not have layout 6813 // Force it by setting the zoom level 6814 style.zoom = 1; 6815 6816 // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652 6817 // if value === "", then remove inline opacity #12685 6818 if ( ( value >= 1 || value === "" ) && 6819 jQuery.trim( filter.replace( ralpha, "" ) ) === "" && 6820 style.removeAttribute ) { 6821 6822 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText 6823 // if "filter:" is present at all, clearType is disabled, we want to avoid this 6824 // style.removeAttribute is IE Only, but so apparently is this code path... 6825 style.removeAttribute( "filter" ); 6826 6827 // if there is no filter style applied in a css rule or unset inline opacity, we are done 6828 if ( value === "" || currentStyle && !currentStyle.filter ) { 6829 return; 6830 } 6831 } 6832 6833 // otherwise, set new filter values 6834 style.filter = ralpha.test( filter ) ? 6835 filter.replace( ralpha, opacity ) : 6836 filter + " " + opacity; 6837 } 6838 }; 6839} 6840 6841jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight, 6842 function( elem, computed ) { 6843 if ( computed ) { 6844 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right 6845 // Work around by temporarily setting element display to inline-block 6846 return jQuery.swap( elem, { "display": "inline-block" }, 6847 curCSS, [ elem, "marginRight" ] ); 6848 } 6849 } 6850); 6851 6852// These hooks are used by animate to expand properties 6853jQuery.each({ 6854 margin: "", 6855 padding: "", 6856 border: "Width" 6857}, function( prefix, suffix ) { 6858 jQuery.cssHooks[ prefix + suffix ] = { 6859 expand: function( value ) { 6860 var i = 0, 6861 expanded = {}, 6862 6863 // assumes a single number if not a string 6864 parts = typeof value === "string" ? value.split(" ") : [ value ]; 6865 6866 for ( ; i < 4; i++ ) { 6867 expanded[ prefix + cssExpand[ i ] + suffix ] = 6868 parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; 6869 } 6870 6871 return expanded; 6872 } 6873 }; 6874 6875 if ( !rmargin.test( prefix ) ) { 6876 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; 6877 } 6878}); 6879 6880jQuery.fn.extend({ 6881 css: function( name, value ) { 6882 return access( this, function( elem, name, value ) { 6883 var styles, len, 6884 map = {}, 6885 i = 0; 6886 6887 if ( jQuery.isArray( name ) ) { 6888 styles = getStyles( elem ); 6889 len = name.length; 6890 6891 for ( ; i < len; i++ ) { 6892 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); 6893 } 6894 6895 return map; 6896 } 6897 6898 return value !== undefined ? 6899 jQuery.style( elem, name, value ) : 6900 jQuery.css( elem, name ); 6901 }, name, value, arguments.length > 1 ); 6902 }, 6903 show: function() { 6904 return showHide( this, true ); 6905 }, 6906 hide: function() { 6907 return showHide( this ); 6908 }, 6909 toggle: function( state ) { 6910 if ( typeof state === "boolean" ) { 6911 return state ? this.show() : this.hide(); 6912 } 6913 6914 return this.each(function() { 6915 if ( isHidden( this ) ) { 6916 jQuery( this ).show(); 6917 } else { 6918 jQuery( this ).hide(); 6919 } 6920 }); 6921 } 6922}); 6923 6924 6925function Tween( elem, options, prop, end, easing ) { 6926 return new Tween.prototype.init( elem, options, prop, end, easing ); 6927} 6928jQuery.Tween = Tween; 6929 6930Tween.prototype = { 6931 constructor: Tween, 6932 init: function( elem, options, prop, end, easing, unit ) { 6933 this.elem = elem; 6934 this.prop = prop; 6935 this.easing = easing || "swing"; 6936 this.options = options; 6937 this.start = this.now = this.cur(); 6938 this.end = end; 6939 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); 6940 }, 6941 cur: function() { 6942 var hooks = Tween.propHooks[ this.prop ]; 6943 6944 return hooks && hooks.get ? 6945 hooks.get( this ) : 6946 Tween.propHooks._default.get( this ); 6947 }, 6948 run: function( percent ) { 6949 var eased, 6950 hooks = Tween.propHooks[ this.prop ]; 6951 6952 if ( this.options.duration ) { 6953 this.pos = eased = jQuery.easing[ this.easing ]( 6954 percent, this.options.duration * percent, 0, 1, this.options.duration 6955 ); 6956 } else { 6957 this.pos = eased = percent; 6958 } 6959 this.now = ( this.end - this.start ) * eased + this.start; 6960 6961 if ( this.options.step ) { 6962 this.options.step.call( this.elem, this.now, this ); 6963 } 6964 6965 if ( hooks && hooks.set ) { 6966 hooks.set( this ); 6967 } else { 6968 Tween.propHooks._default.set( this ); 6969 } 6970 return this; 6971 } 6972}; 6973 6974Tween.prototype.init.prototype = Tween.prototype; 6975 6976Tween.propHooks = { 6977 _default: { 6978 get: function( tween ) { 6979 var result; 6980 6981 if ( tween.elem[ tween.prop ] != null && 6982 (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { 6983 return tween.elem[ tween.prop ]; 6984 } 6985 6986 // passing an empty string as a 3rd parameter to .css will automatically 6987 // attempt a parseFloat and fallback to a string if the parse fails 6988 // so, simple values such as "10px" are parsed to Float. 6989 // complex values such as "rotate(1rad)" are returned as is. 6990 result = jQuery.css( tween.elem, tween.prop, "" ); 6991 // Empty strings, null, undefined and "auto" are converted to 0. 6992 return !result || result === "auto" ? 0 : result; 6993 }, 6994 set: function( tween ) { 6995 // use step hook for back compat - use cssHook if its there - use .style if its 6996 // available and use plain properties where available 6997 if ( jQuery.fx.step[ tween.prop ] ) { 6998 jQuery.fx.step[ tween.prop ]( tween ); 6999 } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { 7000 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); 7001 } else { 7002 tween.elem[ tween.prop ] = tween.now; 7003 } 7004 } 7005 } 7006}; 7007 7008// Support: IE <=9 7009// Panic based approach to setting things on disconnected nodes 7010 7011Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { 7012 set: function( tween ) { 7013 if ( tween.elem.nodeType && tween.elem.parentNode ) { 7014 tween.elem[ tween.prop ] = tween.now; 7015 } 7016 } 7017}; 7018 7019jQuery.easing = { 7020 linear: function( p ) { 7021 return p; 7022 }, 7023 swing: function( p ) { 7024 return 0.5 - Math.cos( p * Math.PI ) / 2; 7025 } 7026}; 7027 7028jQuery.fx = Tween.prototype.init; 7029 7030// Back Compat <1.8 extension point 7031jQuery.fx.step = {}; 7032 7033 7034 7035 7036var 7037 fxNow, timerId, 7038 rfxtypes = /^(?:toggle|show|hide)$/, 7039 rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ), 7040 rrun = /queueHooks$/, 7041 animationPrefilters = [ defaultPrefilter ], 7042 tweeners = { 7043 "*": [ function( prop, value ) { 7044 var tween = this.createTween( prop, value ), 7045 target = tween.cur(), 7046 parts = rfxnum.exec( value ), 7047 unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), 7048 7049 // Starting value computation is required for potential unit mismatches 7050 start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) && 7051 rfxnum.exec( jQuery.css( tween.elem, prop ) ), 7052 scale = 1, 7053 maxIterations = 20; 7054 7055 if ( start && start[ 3 ] !== unit ) { 7056 // Trust units reported by jQuery.css 7057 unit = unit || start[ 3 ]; 7058 7059 // Make sure we update the tween properties later on 7060 parts = parts || []; 7061 7062 // Iteratively approximate from a nonzero starting point 7063 start = +target || 1; 7064 7065 do { 7066 // If previous iteration zeroed out, double until we get *something* 7067 // Use a string for doubling factor so we don't accidentally see scale as unchanged below 7068 scale = scale || ".5"; 7069 7070 // Adjust and apply 7071 start = start / scale; 7072 jQuery.style( tween.elem, prop, start + unit ); 7073 7074 // Update scale, tolerating zero or NaN from tween.cur() 7075 // And breaking the loop if scale is unchanged or perfect, or if we've just had enough 7076 } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); 7077 } 7078 7079 // Update tween properties 7080 if ( parts ) { 7081 start = tween.start = +start || +target || 0; 7082 tween.unit = unit; 7083 // If a +=/-= token was provided, we're doing a relative animation 7084 tween.end = parts[ 1 ] ? 7085 start + ( parts[ 1 ] + 1 ) * parts[ 2 ] : 7086 +parts[ 2 ]; 7087 } 7088 7089 return tween; 7090 } ] 7091 }; 7092 7093// Animations created synchronously will run synchronously 7094function createFxNow() { 7095 setTimeout(function() { 7096 fxNow = undefined; 7097 }); 7098 return ( fxNow = jQuery.now() ); 7099} 7100 7101// Generate parameters to create a standard animation 7102function genFx( type, includeWidth ) { 7103 var which, 7104 attrs = { height: type }, 7105 i = 0; 7106 7107 // if we include width, step value is 1 to do all cssExpand values, 7108 // if we don't include width, step value is 2 to skip over Left and Right 7109 includeWidth = includeWidth ? 1 : 0; 7110 for ( ; i < 4 ; i += 2 - includeWidth ) { 7111 which = cssExpand[ i ]; 7112 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; 7113 } 7114 7115 if ( includeWidth ) { 7116 attrs.opacity = attrs.width = type; 7117 } 7118 7119 return attrs; 7120} 7121 7122function createTween( value, prop, animation ) { 7123 var tween, 7124 collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), 7125 index = 0, 7126 length = collection.length; 7127 for ( ; index < length; index++ ) { 7128 if ( (tween = collection[ index ].call( animation, prop, value )) ) { 7129 7130 // we're done with this property 7131 return tween; 7132 } 7133 } 7134} 7135 7136function defaultPrefilter( elem, props, opts ) { 7137 /* jshint validthis: true */ 7138 var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay, 7139 anim = this, 7140 orig = {}, 7141 style = elem.style, 7142 hidden = elem.nodeType && isHidden( elem ), 7143 dataShow = jQuery._data( elem, "fxshow" ); 7144 7145 // handle queue: false promises 7146 if ( !opts.queue ) { 7147 hooks = jQuery._queueHooks( elem, "fx" ); 7148 if ( hooks.unqueued == null ) { 7149 hooks.unqueued = 0; 7150 oldfire = hooks.empty.fire; 7151 hooks.empty.fire = function() { 7152 if ( !hooks.unqueued ) { 7153 oldfire(); 7154 } 7155 }; 7156 } 7157 hooks.unqueued++; 7158 7159 anim.always(function() { 7160 // doing this makes sure that the complete handler will be called 7161 // before this completes 7162 anim.always(function() { 7163 hooks.unqueued--; 7164 if ( !jQuery.queue( elem, "fx" ).length ) { 7165 hooks.empty.fire(); 7166 } 7167 }); 7168 }); 7169 } 7170 7171 // height/width overflow pass 7172 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { 7173 // Make sure that nothing sneaks out 7174 // Record all 3 overflow attributes because IE does not 7175 // change the overflow attribute when overflowX and 7176 // overflowY are set to the same value 7177 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; 7178 7179 // Set display property to inline-block for height/width 7180 // animations on inline elements that are having width/height animated 7181 display = jQuery.css( elem, "display" ); 7182 7183 // Test default display if display is currently "none" 7184 checkDisplay = display === "none" ? 7185 jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display; 7186 7187 if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) { 7188 7189 // inline-level elements accept inline-block; 7190 // block-level elements need to be inline with layout 7191 if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) { 7192 style.display = "inline-block"; 7193 } else { 7194 style.zoom = 1; 7195 } 7196 } 7197 } 7198 7199 if ( opts.overflow ) { 7200 style.overflow = "hidden"; 7201 if ( !support.shrinkWrapBlocks() ) { 7202 anim.always(function() { 7203 style.overflow = opts.overflow[ 0 ]; 7204 style.overflowX = opts.overflow[ 1 ]; 7205 style.overflowY = opts.overflow[ 2 ]; 7206 }); 7207 } 7208 } 7209 7210 // show/hide pass 7211 for ( prop in props ) { 7212 value = props[ prop ]; 7213 if ( rfxtypes.exec( value ) ) { 7214 delete props[ prop ]; 7215 toggle = toggle || value === "toggle"; 7216 if ( value === ( hidden ? "hide" : "show" ) ) { 7217 7218 // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden 7219 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { 7220 hidden = true; 7221 } else { 7222 continue; 7223 } 7224 } 7225 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); 7226 7227 // Any non-fx value stops us from restoring the original display value 7228 } else { 7229 display = undefined; 7230 } 7231 } 7232 7233 if ( !jQuery.isEmptyObject( orig ) ) { 7234 if ( dataShow ) { 7235 if ( "hidden" in dataShow ) { 7236 hidden = dataShow.hidden; 7237 } 7238 } else { 7239 dataShow = jQuery._data( elem, "fxshow", {} ); 7240 } 7241 7242 // store state if its toggle - enables .stop().toggle() to "reverse" 7243 if ( toggle ) { 7244 dataShow.hidden = !hidden; 7245 } 7246 if ( hidden ) { 7247 jQuery( elem ).show(); 7248 } else { 7249 anim.done(function() { 7250 jQuery( elem ).hide(); 7251 }); 7252 } 7253 anim.done(function() { 7254 var prop; 7255 jQuery._removeData( elem, "fxshow" ); 7256 for ( prop in orig ) { 7257 jQuery.style( elem, prop, orig[ prop ] ); 7258 } 7259 }); 7260 for ( prop in orig ) { 7261 tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); 7262 7263 if ( !( prop in dataShow ) ) { 7264 dataShow[ prop ] = tween.start; 7265 if ( hidden ) { 7266 tween.end = tween.start; 7267 tween.start = prop === "width" || prop === "height" ? 1 : 0; 7268 } 7269 } 7270 } 7271 7272 // If this is a noop like .hide().hide(), restore an overwritten display value 7273 } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) { 7274 style.display = display; 7275 } 7276} 7277 7278function propFilter( props, specialEasing ) { 7279 var index, name, easing, value, hooks; 7280 7281 // camelCase, specialEasing and expand cssHook pass 7282 for ( index in props ) { 7283 name = jQuery.camelCase( index ); 7284 easing = specialEasing[ name ]; 7285 value = props[ index ]; 7286 if ( jQuery.isArray( value ) ) { 7287 easing = value[ 1 ]; 7288 value = props[ index ] = value[ 0 ]; 7289 } 7290 7291 if ( index !== name ) { 7292 props[ name ] = value; 7293 delete props[ index ]; 7294 } 7295 7296 hooks = jQuery.cssHooks[ name ]; 7297 if ( hooks && "expand" in hooks ) { 7298 value = hooks.expand( value ); 7299 delete props[ name ]; 7300 7301 // not quite $.extend, this wont overwrite keys already present. 7302 // also - reusing 'index' from above because we have the correct "name" 7303 for ( index in value ) { 7304 if ( !( index in props ) ) { 7305 props[ index ] = value[ index ]; 7306 specialEasing[ index ] = easing; 7307 } 7308 } 7309 } else { 7310 specialEasing[ name ] = easing; 7311 } 7312 } 7313} 7314 7315function Animation( elem, properties, options ) { 7316 var result, 7317 stopped, 7318 index = 0, 7319 length = animationPrefilters.length, 7320 deferred = jQuery.Deferred().always( function() { 7321 // don't match elem in the :animated selector 7322 delete tick.elem; 7323 }), 7324 tick = function() { 7325 if ( stopped ) { 7326 return false; 7327 } 7328 var currentTime = fxNow || createFxNow(), 7329 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), 7330 // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497) 7331 temp = remaining / animation.duration || 0, 7332 percent = 1 - temp, 7333 index = 0, 7334 length = animation.tweens.length; 7335 7336 for ( ; index < length ; index++ ) { 7337 animation.tweens[ index ].run( percent ); 7338 } 7339 7340 deferred.notifyWith( elem, [ animation, percent, remaining ]); 7341 7342 if ( percent < 1 && length ) { 7343 return remaining; 7344 } else { 7345 deferred.resolveWith( elem, [ animation ] ); 7346 return false; 7347 } 7348 }, 7349 animation = deferred.promise({ 7350 elem: elem, 7351 props: jQuery.extend( {}, properties ), 7352 opts: jQuery.extend( true, { specialEasing: {} }, options ), 7353 originalProperties: properties, 7354 originalOptions: options, 7355 startTime: fxNow || createFxNow(), 7356 duration: options.duration, 7357 tweens: [], 7358 createTween: function( prop, end ) { 7359 var tween = jQuery.Tween( elem, animation.opts, prop, end, 7360 animation.opts.specialEasing[ prop ] || animation.opts.easing ); 7361 animation.tweens.push( tween ); 7362 return tween; 7363 }, 7364 stop: function( gotoEnd ) { 7365 var index = 0, 7366 // if we are going to the end, we want to run all the tweens 7367 // otherwise we skip this part 7368 length = gotoEnd ? animation.tweens.length : 0; 7369 if ( stopped ) { 7370 return this; 7371 } 7372 stopped = true; 7373 for ( ; index < length ; index++ ) { 7374 animation.tweens[ index ].run( 1 ); 7375 } 7376 7377 // resolve when we played the last frame 7378 // otherwise, reject 7379 if ( gotoEnd ) { 7380 deferred.resolveWith( elem, [ animation, gotoEnd ] ); 7381 } else { 7382 deferred.rejectWith( elem, [ animation, gotoEnd ] ); 7383 } 7384 return this; 7385 } 7386 }), 7387 props = animation.props; 7388 7389 propFilter( props, animation.opts.specialEasing ); 7390 7391 for ( ; index < length ; index++ ) { 7392 result = animationPrefilters[ index ].call( animation, elem, props, animation.opts ); 7393 if ( result ) { 7394 return result; 7395 } 7396 } 7397 7398 jQuery.map( props, createTween, animation ); 7399 7400 if ( jQuery.isFunction( animation.opts.start ) ) { 7401 animation.opts.start.call( elem, animation ); 7402 } 7403 7404 jQuery.fx.timer( 7405 jQuery.extend( tick, { 7406 elem: elem, 7407 anim: animation, 7408 queue: animation.opts.queue 7409 }) 7410 ); 7411 7412 // attach callbacks from options 7413 return animation.progress( animation.opts.progress ) 7414 .done( animation.opts.done, animation.opts.complete ) 7415 .fail( animation.opts.fail ) 7416 .always( animation.opts.always ); 7417} 7418 7419jQuery.Animation = jQuery.extend( Animation, { 7420 tweener: function( props, callback ) { 7421 if ( jQuery.isFunction( props ) ) { 7422 callback = props; 7423 props = [ "*" ]; 7424 } else { 7425 props = props.split(" "); 7426 } 7427 7428 var prop, 7429 index = 0, 7430 length = props.length; 7431 7432 for ( ; index < length ; index++ ) { 7433 prop = props[ index ]; 7434 tweeners[ prop ] = tweeners[ prop ] || []; 7435 tweeners[ prop ].unshift( callback ); 7436 } 7437 }, 7438 7439 prefilter: function( callback, prepend ) { 7440 if ( prepend ) { 7441 animationPrefilters.unshift( callback ); 7442 } else { 7443 animationPrefilters.push( callback ); 7444 } 7445 } 7446}); 7447 7448jQuery.speed = function( speed, easing, fn ) { 7449 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { 7450 complete: fn || !fn && easing || 7451 jQuery.isFunction( speed ) && speed, 7452 duration: speed, 7453 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing 7454 }; 7455 7456 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : 7457 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; 7458 7459 // normalize opt.queue - true/undefined/null -> "fx" 7460 if ( opt.queue == null || opt.queue === true ) { 7461 opt.queue = "fx"; 7462 } 7463 7464 // Queueing 7465 opt.old = opt.complete; 7466 7467 opt.complete = function() { 7468 if ( jQuery.isFunction( opt.old ) ) { 7469 opt.old.call( this ); 7470 } 7471 7472 if ( opt.queue ) { 7473 jQuery.dequeue( this, opt.queue ); 7474 } 7475 }; 7476 7477 return opt; 7478}; 7479 7480jQuery.fn.extend({ 7481 fadeTo: function( speed, to, easing, callback ) { 7482 7483 // show any hidden elements after setting opacity to 0 7484 return this.filter( isHidden ).css( "opacity", 0 ).show() 7485 7486 // animate to the value specified 7487 .end().animate({ opacity: to }, speed, easing, callback ); 7488 }, 7489 animate: function( prop, speed, easing, callback ) { 7490 var empty = jQuery.isEmptyObject( prop ), 7491 optall = jQuery.speed( speed, easing, callback ), 7492 doAnimation = function() { 7493 // Operate on a copy of prop so per-property easing won't be lost 7494 var anim = Animation( this, jQuery.extend( {}, prop ), optall ); 7495 7496 // Empty animations, or finishing resolves immediately 7497 if ( empty || jQuery._data( this, "finish" ) ) { 7498 anim.stop( true ); 7499 } 7500 }; 7501 doAnimation.finish = doAnimation; 7502 7503 return empty || optall.queue === false ? 7504 this.each( doAnimation ) : 7505 this.queue( optall.queue, doAnimation ); 7506 }, 7507 stop: function( type, clearQueue, gotoEnd ) { 7508 var stopQueue = function( hooks ) { 7509 var stop = hooks.stop; 7510 delete hooks.stop; 7511 stop( gotoEnd ); 7512 }; 7513 7514 if ( typeof type !== "string" ) { 7515 gotoEnd = clearQueue; 7516 clearQueue = type; 7517 type = undefined; 7518 } 7519 if ( clearQueue && type !== false ) { 7520 this.queue( type || "fx", [] ); 7521 } 7522 7523 return this.each(function() { 7524 var dequeue = true, 7525 index = type != null && type + "queueHooks", 7526 timers = jQuery.timers, 7527 data = jQuery._data( this ); 7528 7529 if ( index ) { 7530 if ( data[ index ] && data[ index ].stop ) { 7531 stopQueue( data[ index ] ); 7532 } 7533 } else { 7534 for ( index in data ) { 7535 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { 7536 stopQueue( data[ index ] ); 7537 } 7538 } 7539 } 7540 7541 for ( index = timers.length; index--; ) { 7542 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { 7543 timers[ index ].anim.stop( gotoEnd ); 7544 dequeue = false; 7545 timers.splice( index, 1 ); 7546 } 7547 } 7548 7549 // start the next in the queue if the last step wasn't forced 7550 // timers currently will call their complete callbacks, which will dequeue 7551 // but only if they were gotoEnd 7552 if ( dequeue || !gotoEnd ) { 7553 jQuery.dequeue( this, type ); 7554 } 7555 }); 7556 }, 7557 finish: function( type ) { 7558 if ( type !== false ) { 7559 type = type || "fx"; 7560 } 7561 return this.each(function() { 7562 var index, 7563 data = jQuery._data( this ), 7564 queue = data[ type + "queue" ], 7565 hooks = data[ type + "queueHooks" ], 7566 timers = jQuery.timers, 7567 length = queue ? queue.length : 0; 7568 7569 // enable finishing flag on private data 7570 data.finish = true; 7571 7572 // empty the queue first 7573 jQuery.queue( this, type, [] ); 7574 7575 if ( hooks && hooks.stop ) { 7576 hooks.stop.call( this, true ); 7577 } 7578 7579 // look for any active animations, and finish them 7580 for ( index = timers.length; index--; ) { 7581 if ( timers[ index ].elem === this && timers[ index ].queue === type ) { 7582 timers[ index ].anim.stop( true ); 7583 timers.splice( index, 1 ); 7584 } 7585 } 7586 7587 // look for any animations in the old queue and finish them 7588 for ( index = 0; index < length; index++ ) { 7589 if ( queue[ index ] && queue[ index ].finish ) { 7590 queue[ index ].finish.call( this ); 7591 } 7592 } 7593 7594 // turn off finishing flag 7595 delete data.finish; 7596 }); 7597 } 7598}); 7599 7600jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { 7601 var cssFn = jQuery.fn[ name ]; 7602 jQuery.fn[ name ] = function( speed, easing, callback ) { 7603 return speed == null || typeof speed === "boolean" ? 7604 cssFn.apply( this, arguments ) : 7605 this.animate( genFx( name, true ), speed, easing, callback ); 7606 }; 7607}); 7608 7609// Generate shortcuts for custom animations 7610jQuery.each({ 7611 slideDown: genFx("show"), 7612 slideUp: genFx("hide"), 7613 slideToggle: genFx("toggle"), 7614 fadeIn: { opacity: "show" }, 7615 fadeOut: { opacity: "hide" }, 7616 fadeToggle: { opacity: "toggle" } 7617}, function( name, props ) { 7618 jQuery.fn[ name ] = function( speed, easing, callback ) { 7619 return this.animate( props, speed, easing, callback ); 7620 }; 7621}); 7622 7623jQuery.timers = []; 7624jQuery.fx.tick = function() { 7625 var timer, 7626 timers = jQuery.timers, 7627 i = 0; 7628 7629 fxNow = jQuery.now(); 7630 7631 for ( ; i < timers.length; i++ ) { 7632 timer = timers[ i ]; 7633 // Checks the timer has not already been removed 7634 if ( !timer() && timers[ i ] === timer ) { 7635 timers.splice( i--, 1 ); 7636 } 7637 } 7638 7639 if ( !timers.length ) { 7640 jQuery.fx.stop(); 7641 } 7642 fxNow = undefined; 7643}; 7644 7645jQuery.fx.timer = function( timer ) { 7646 jQuery.timers.push( timer ); 7647 if ( timer() ) { 7648 jQuery.fx.start(); 7649 } else { 7650 jQuery.timers.pop(); 7651 } 7652}; 7653 7654jQuery.fx.interval = 13; 7655 7656jQuery.fx.start = function() { 7657 if ( !timerId ) { 7658 timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); 7659 } 7660}; 7661 7662jQuery.fx.stop = function() { 7663 clearInterval( timerId ); 7664 timerId = null; 7665}; 7666 7667jQuery.fx.speeds = { 7668 slow: 600, 7669 fast: 200, 7670 // Default speed 7671 _default: 400 7672}; 7673 7674 7675// Based off of the plugin by Clint Helfers, with permission. 7676// http://blindsignals.com/index.php/2009/07/jquery-delay/ 7677jQuery.fn.delay = function( time, type ) { 7678 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; 7679 type = type || "fx"; 7680 7681 return this.queue( type, function( next, hooks ) { 7682 var timeout = setTimeout( next, time ); 7683 hooks.stop = function() { 7684 clearTimeout( timeout ); 7685 }; 7686 }); 7687}; 7688 7689 7690(function() { 7691 // Minified: var a,b,c,d,e 7692 var input, div, select, a, opt; 7693 7694 // Setup 7695 div = document.createElement( "div" ); 7696 div.setAttribute( "className", "t" ); 7697 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; 7698 a = div.getElementsByTagName("a")[ 0 ]; 7699 7700 // First batch of tests. 7701 select = document.createElement("select"); 7702 opt = select.appendChild( document.createElement("option") ); 7703 input = div.getElementsByTagName("input")[ 0 ]; 7704 7705 a.style.cssText = "top:1px"; 7706 7707 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) 7708 support.getSetAttribute = div.className !== "t"; 7709 7710 // Get the style information from getAttribute 7711 // (IE uses .cssText instead) 7712 support.style = /top/.test( a.getAttribute("style") ); 7713 7714 // Make sure that URLs aren't manipulated 7715 // (IE normalizes it by default) 7716 support.hrefNormalized = a.getAttribute("href") === "/a"; 7717 7718 // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) 7719 support.checkOn = !!input.value; 7720 7721 // Make sure that a selected-by-default option has a working selected property. 7722 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) 7723 support.optSelected = opt.selected; 7724 7725 // Tests for enctype support on a form (#6743) 7726 support.enctype = !!document.createElement("form").enctype; 7727 7728 // Make sure that the options inside disabled selects aren't marked as disabled 7729 // (WebKit marks them as disabled) 7730 select.disabled = true; 7731 support.optDisabled = !opt.disabled; 7732 7733 // Support: IE8 only 7734 // Check if we can trust getAttribute("value") 7735 input = document.createElement( "input" ); 7736 input.setAttribute( "value", "" ); 7737 support.input = input.getAttribute( "value" ) === ""; 7738 7739 // Check if an input maintains its value after becoming a radio 7740 input.value = "t"; 7741 input.setAttribute( "type", "radio" ); 7742 support.radioValue = input.value === "t"; 7743})(); 7744 7745 7746var rreturn = /\r/g; 7747 7748jQuery.fn.extend({ 7749 val: function( value ) { 7750 var hooks, ret, isFunction, 7751 elem = this[0]; 7752 7753 if ( !arguments.length ) { 7754 if ( elem ) { 7755 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; 7756 7757 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { 7758 return ret; 7759 } 7760 7761 ret = elem.value; 7762 7763 return typeof ret === "string" ? 7764 // handle most common string cases 7765 ret.replace(rreturn, "") : 7766 // handle cases where value is null/undef or number 7767 ret == null ? "" : ret; 7768 } 7769 7770 return; 7771 } 7772 7773 isFunction = jQuery.isFunction( value ); 7774 7775 return this.each(function( i ) { 7776 var val; 7777 7778 if ( this.nodeType !== 1 ) { 7779 return; 7780 } 7781 7782 if ( isFunction ) { 7783 val = value.call( this, i, jQuery( this ).val() ); 7784 } else { 7785 val = value; 7786 } 7787 7788 // Treat null/undefined as ""; convert numbers to string 7789 if ( val == null ) { 7790 val = ""; 7791 } else if ( typeof val === "number" ) { 7792 val += ""; 7793 } else if ( jQuery.isArray( val ) ) { 7794 val = jQuery.map( val, function( value ) { 7795 return value == null ? "" : value + ""; 7796 }); 7797 } 7798 7799 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; 7800 7801 // If set returns undefined, fall back to normal setting 7802 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { 7803 this.value = val; 7804 } 7805 }); 7806 } 7807}); 7808 7809jQuery.extend({ 7810 valHooks: { 7811 option: { 7812 get: function( elem ) { 7813 var val = jQuery.find.attr( elem, "value" ); 7814 return val != null ? 7815 val : 7816 // Support: IE10-11+ 7817 // option.text throws exceptions (#14686, #14858) 7818 jQuery.trim( jQuery.text( elem ) ); 7819 } 7820 }, 7821 select: { 7822 get: function( elem ) { 7823 var value, option, 7824 options = elem.options, 7825 index = elem.selectedIndex, 7826 one = elem.type === "select-one" || index < 0, 7827 values = one ? null : [], 7828 max = one ? index + 1 : options.length, 7829 i = index < 0 ? 7830 max : 7831 one ? index : 0; 7832 7833 // Loop through all the selected options 7834 for ( ; i < max; i++ ) { 7835 option = options[ i ]; 7836 7837 // oldIE doesn't update selected after form reset (#2551) 7838 if ( ( option.selected || i === index ) && 7839 // Don't return options that are disabled or in a disabled optgroup 7840 ( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && 7841 ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { 7842 7843 // Get the specific value for the option 7844 value = jQuery( option ).val(); 7845 7846 // We don't need an array for one selects 7847 if ( one ) { 7848 return value; 7849 } 7850 7851 // Multi-Selects return an array 7852 values.push( value ); 7853 } 7854 } 7855 7856 return values; 7857 }, 7858 7859 set: function( elem, value ) { 7860 var optionSet, option, 7861 options = elem.options, 7862 values = jQuery.makeArray( value ), 7863 i = options.length; 7864 7865 while ( i-- ) { 7866 option = options[ i ]; 7867 7868 if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) { 7869 7870 // Support: IE6 7871 // When new option element is added to select box we need to 7872 // force reflow of newly added node in order to workaround delay 7873 // of initialization properties 7874 try { 7875 option.selected = optionSet = true; 7876 7877 } catch ( _ ) { 7878 7879 // Will be executed only in IE6 7880 option.scrollHeight; 7881 } 7882 7883 } else { 7884 option.selected = false; 7885 } 7886 } 7887 7888 // Force browsers to behave consistently when non-matching value is set 7889 if ( !optionSet ) { 7890 elem.selectedIndex = -1; 7891 } 7892 7893 return options; 7894 } 7895 } 7896 } 7897}); 7898 7899// Radios and checkboxes getter/setter 7900jQuery.each([ "radio", "checkbox" ], function() { 7901 jQuery.valHooks[ this ] = { 7902 set: function( elem, value ) { 7903 if ( jQuery.isArray( value ) ) { 7904 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); 7905 } 7906 } 7907 }; 7908 if ( !support.checkOn ) { 7909 jQuery.valHooks[ this ].get = function( elem ) { 7910 // Support: Webkit 7911 // "" is returned instead of "on" if a value isn't specified 7912 return elem.getAttribute("value") === null ? "on" : elem.value; 7913 }; 7914 } 7915}); 7916 7917 7918 7919 7920var nodeHook, boolHook, 7921 attrHandle = jQuery.expr.attrHandle, 7922 ruseDefault = /^(?:checked|selected)$/i, 7923 getSetAttribute = support.getSetAttribute, 7924 getSetInput = support.input; 7925 7926jQuery.fn.extend({ 7927 attr: function( name, value ) { 7928 return access( this, jQuery.attr, name, value, arguments.length > 1 ); 7929 }, 7930 7931 removeAttr: function( name ) { 7932 return this.each(function() { 7933 jQuery.removeAttr( this, name ); 7934 }); 7935 } 7936}); 7937 7938jQuery.extend({ 7939 attr: function( elem, name, value ) { 7940 var hooks, ret, 7941 nType = elem.nodeType; 7942 7943 // don't get/set attributes on text, comment and attribute nodes 7944 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { 7945 return; 7946 } 7947 7948 // Fallback to prop when attributes are not supported 7949 if ( typeof elem.getAttribute === strundefined ) { 7950 return jQuery.prop( elem, name, value ); 7951 } 7952 7953 // All attributes are lowercase 7954 // Grab necessary hook if one is defined 7955 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { 7956 name = name.toLowerCase(); 7957 hooks = jQuery.attrHooks[ name ] || 7958 ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); 7959 } 7960 7961 if ( value !== undefined ) { 7962 7963 if ( value === null ) { 7964 jQuery.removeAttr( elem, name ); 7965 7966 } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { 7967 return ret; 7968 7969 } else { 7970 elem.setAttribute( name, value + "" ); 7971 return value; 7972 } 7973 7974 } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { 7975 return ret; 7976 7977 } else { 7978 ret = jQuery.find.attr( elem, name ); 7979 7980 // Non-existent attributes return null, we normalize to undefined 7981 return ret == null ? 7982 undefined : 7983 ret; 7984 } 7985 }, 7986 7987 removeAttr: function( elem, value ) { 7988 var name, propName, 7989 i = 0, 7990 attrNames = value && value.match( rnotwhite ); 7991 7992 if ( attrNames && elem.nodeType === 1 ) { 7993 while ( (name = attrNames[i++]) ) { 7994 propName = jQuery.propFix[ name ] || name; 7995 7996 // Boolean attributes get special treatment (#10870) 7997 if ( jQuery.expr.match.bool.test( name ) ) { 7998 // Set corresponding property to false 7999 if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { 8000 elem[ propName ] = false; 8001 // Support: IE<9 8002 // Also clear defaultChecked/defaultSelected (if appropriate) 8003 } else { 8004 elem[ jQuery.camelCase( "default-" + name ) ] = 8005 elem[ propName ] = false; 8006 } 8007 8008 // See #9699 for explanation of this approach (setting first, then removal) 8009 } else { 8010 jQuery.attr( elem, name, "" ); 8011 } 8012 8013 elem.removeAttribute( getSetAttribute ? name : propName ); 8014 } 8015 } 8016 }, 8017 8018 attrHooks: { 8019 type: { 8020 set: function( elem, value ) { 8021 if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { 8022 // Setting the type on a radio button after the value resets the value in IE6-9 8023 // Reset value to default in case type is set after value during creation 8024 var val = elem.value; 8025 elem.setAttribute( "type", value ); 8026 if ( val ) { 8027 elem.value = val; 8028 } 8029 return value; 8030 } 8031 } 8032 } 8033 } 8034}); 8035 8036// Hook for boolean attributes 8037boolHook = { 8038 set: function( elem, value, name ) { 8039 if ( value === false ) { 8040 // Remove boolean attributes when set to false 8041 jQuery.removeAttr( elem, name ); 8042 } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { 8043 // IE<8 needs the *property* name 8044 elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); 8045 8046 // Use defaultChecked and defaultSelected for oldIE 8047 } else { 8048 elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; 8049 } 8050 8051 return name; 8052 } 8053}; 8054 8055// Retrieve booleans specially 8056jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { 8057 8058 var getter = attrHandle[ name ] || jQuery.find.attr; 8059 8060 attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? 8061 function( elem, name, isXML ) { 8062 var ret, handle; 8063 if ( !isXML ) { 8064 // Avoid an infinite loop by temporarily removing this function from the getter 8065 handle = attrHandle[ name ]; 8066 attrHandle[ name ] = ret; 8067 ret = getter( elem, name, isXML ) != null ? 8068 name.toLowerCase() : 8069 null; 8070 attrHandle[ name ] = handle; 8071 } 8072 return ret; 8073 } : 8074 function( elem, name, isXML ) { 8075 if ( !isXML ) { 8076 return elem[ jQuery.camelCase( "default-" + name ) ] ? 8077 name.toLowerCase() : 8078 null; 8079 } 8080 }; 8081}); 8082 8083// fix oldIE attroperties 8084if ( !getSetInput || !getSetAttribute ) { 8085 jQuery.attrHooks.value = { 8086 set: function( elem, value, name ) { 8087 if ( jQuery.nodeName( elem, "input" ) ) { 8088 // Does not return so that setAttribute is also used 8089 elem.defaultValue = value; 8090 } else { 8091 // Use nodeHook if defined (#1954); otherwise setAttribute is fine 8092 return nodeHook && nodeHook.set( elem, value, name ); 8093 } 8094 } 8095 }; 8096} 8097 8098// IE6/7 do not support getting/setting some attributes with get/setAttribute 8099if ( !getSetAttribute ) { 8100 8101 // Use this for any attribute in IE6/7 8102 // This fixes almost every IE6/7 issue 8103 nodeHook = { 8104 set: function( elem, value, name ) { 8105 // Set the existing or create a new attribute node 8106 var ret = elem.getAttributeNode( name ); 8107 if ( !ret ) { 8108 elem.setAttributeNode( 8109 (ret = elem.ownerDocument.createAttribute( name )) 8110 ); 8111 } 8112 8113 ret.value = value += ""; 8114 8115 // Break association with cloned elements by also using setAttribute (#9646) 8116 if ( name === "value" || value === elem.getAttribute( name ) ) { 8117 return value; 8118 } 8119 } 8120 }; 8121 8122 // Some attributes are constructed with empty-string values when not defined 8123 attrHandle.id = attrHandle.name = attrHandle.coords = 8124 function( elem, name, isXML ) { 8125 var ret; 8126 if ( !isXML ) { 8127 return (ret = elem.getAttributeNode( name )) && ret.value !== "" ? 8128 ret.value : 8129 null; 8130 } 8131 }; 8132 8133 // Fixing value retrieval on a button requires this module 8134 jQuery.valHooks.button = { 8135 get: function( elem, name ) { 8136 var ret = elem.getAttributeNode( name ); 8137 if ( ret && ret.specified ) { 8138 return ret.value; 8139 } 8140 }, 8141 set: nodeHook.set 8142 }; 8143 8144 // Set contenteditable to false on removals(#10429) 8145 // Setting to empty string throws an error as an invalid value 8146 jQuery.attrHooks.contenteditable = { 8147 set: function( elem, value, name ) { 8148 nodeHook.set( elem, value === "" ? false : value, name ); 8149 } 8150 }; 8151 8152 // Set width and height to auto instead of 0 on empty string( Bug #8150 ) 8153 // This is for removals 8154 jQuery.each([ "width", "height" ], function( i, name ) { 8155 jQuery.attrHooks[ name ] = { 8156 set: function( elem, value ) { 8157 if ( value === "" ) { 8158 elem.setAttribute( name, "auto" ); 8159 return value; 8160 } 8161 } 8162 }; 8163 }); 8164} 8165 8166if ( !support.style ) { 8167 jQuery.attrHooks.style = { 8168 get: function( elem ) { 8169 // Return undefined in the case of empty string 8170 // Note: IE uppercases css property names, but if we were to .toLowerCase() 8171 // .cssText, that would destroy case senstitivity in URL's, like in "background" 8172 return elem.style.cssText || undefined; 8173 }, 8174 set: function( elem, value ) { 8175 return ( elem.style.cssText = value + "" ); 8176 } 8177 }; 8178} 8179 8180 8181 8182 8183var rfocusable = /^(?:input|select|textarea|button|object)$/i, 8184 rclickable = /^(?:a|area)$/i; 8185 8186jQuery.fn.extend({ 8187 prop: function( name, value ) { 8188 return access( this, jQuery.prop, name, value, arguments.length > 1 ); 8189 }, 8190 8191 removeProp: function( name ) { 8192 name = jQuery.propFix[ name ] || name; 8193 return this.each(function() { 8194 // try/catch handles cases where IE balks (such as removing a property on window) 8195 try { 8196 this[ name ] = undefined; 8197 delete this[ name ]; 8198 } catch( e ) {} 8199 }); 8200 } 8201}); 8202 8203jQuery.extend({ 8204 propFix: { 8205 "for": "htmlFor", 8206 "class": "className" 8207 }, 8208 8209 prop: function( elem, name, value ) { 8210 var ret, hooks, notxml, 8211 nType = elem.nodeType; 8212 8213 // don't get/set properties on text, comment and attribute nodes 8214 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { 8215 return; 8216 } 8217 8218 notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); 8219 8220 if ( notxml ) { 8221 // Fix name and attach hooks 8222 name = jQuery.propFix[ name ] || name; 8223 hooks = jQuery.propHooks[ name ]; 8224 } 8225 8226 if ( value !== undefined ) { 8227 return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? 8228 ret : 8229 ( elem[ name ] = value ); 8230 8231 } else { 8232 return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? 8233 ret : 8234 elem[ name ]; 8235 } 8236 }, 8237 8238 propHooks: { 8239 tabIndex: { 8240 get: function( elem ) { 8241 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set 8242 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ 8243 // Use proper attribute retrieval(#12072) 8244 var tabindex = jQuery.find.attr( elem, "tabindex" ); 8245 8246 return tabindex ? 8247 parseInt( tabindex, 10 ) : 8248 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 8249 0 : 8250 -1; 8251 } 8252 } 8253 } 8254}); 8255 8256// Some attributes require a special call on IE 8257// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx 8258if ( !support.hrefNormalized ) { 8259 // href/src property should get the full normalized URL (#10299/#12915) 8260 jQuery.each([ "href", "src" ], function( i, name ) { 8261 jQuery.propHooks[ name ] = { 8262 get: function( elem ) { 8263 return elem.getAttribute( name, 4 ); 8264 } 8265 }; 8266 }); 8267} 8268 8269// Support: Safari, IE9+ 8270// mis-reports the default selected property of an option 8271// Accessing the parent's selectedIndex property fixes it 8272if ( !support.optSelected ) { 8273 jQuery.propHooks.selected = { 8274 get: function( elem ) { 8275 var parent = elem.parentNode; 8276 8277 if ( parent ) { 8278 parent.selectedIndex; 8279 8280 // Make sure that it also works with optgroups, see #5701 8281 if ( parent.parentNode ) { 8282 parent.parentNode.selectedIndex; 8283 } 8284 } 8285 return null; 8286 } 8287 }; 8288} 8289 8290jQuery.each([ 8291 "tabIndex", 8292 "readOnly", 8293 "maxLength", 8294 "cellSpacing", 8295 "cellPadding", 8296 "rowSpan", 8297 "colSpan", 8298 "useMap", 8299 "frameBorder", 8300 "contentEditable" 8301], function() { 8302 jQuery.propFix[ this.toLowerCase() ] = this; 8303}); 8304 8305// IE6/7 call enctype encoding 8306if ( !support.enctype ) { 8307 jQuery.propFix.enctype = "encoding"; 8308} 8309 8310 8311 8312 8313var rclass = /[\t\r\n\f]/g; 8314 8315jQuery.fn.extend({ 8316 addClass: function( value ) { 8317 var classes, elem, cur, clazz, j, finalValue, 8318 i = 0, 8319 len = this.length, 8320 proceed = typeof value === "string" && value; 8321 8322 if ( jQuery.isFunction( value ) ) { 8323 return this.each(function( j ) { 8324 jQuery( this ).addClass( value.call( this, j, this.className ) ); 8325 }); 8326 } 8327 8328 if ( proceed ) { 8329 // The disjunction here is for better compressibility (see removeClass) 8330 classes = ( value || "" ).match( rnotwhite ) || []; 8331 8332 for ( ; i < len; i++ ) { 8333 elem = this[ i ]; 8334 cur = elem.nodeType === 1 && ( elem.className ? 8335 ( " " + elem.className + " " ).replace( rclass, " " ) : 8336 " " 8337 ); 8338 8339 if ( cur ) { 8340 j = 0; 8341 while ( (clazz = classes[j++]) ) { 8342 if ( cur.indexOf( " " + clazz + " " ) < 0 ) { 8343 cur += clazz + " "; 8344 } 8345 } 8346 8347 // only assign if different to avoid unneeded rendering. 8348 finalValue = jQuery.trim( cur ); 8349 if ( elem.className !== finalValue ) { 8350 elem.className = finalValue; 8351 } 8352 } 8353 } 8354 } 8355 8356 return this; 8357 }, 8358 8359 removeClass: function( value ) { 8360 var classes, elem, cur, clazz, j, finalValue, 8361 i = 0, 8362 len = this.length, 8363 proceed = arguments.length === 0 || typeof value === "string" && value; 8364 8365 if ( jQuery.isFunction( value ) ) { 8366 return this.each(function( j ) { 8367 jQuery( this ).removeClass( value.call( this, j, this.className ) ); 8368 }); 8369 } 8370 if ( proceed ) { 8371 classes = ( value || "" ).match( rnotwhite ) || []; 8372 8373 for ( ; i < len; i++ ) { 8374 elem = this[ i ]; 8375 // This expression is here for better compressibility (see addClass) 8376 cur = elem.nodeType === 1 && ( elem.className ? 8377 ( " " + elem.className + " " ).replace( rclass, " " ) : 8378 "" 8379 ); 8380 8381 if ( cur ) { 8382 j = 0; 8383 while ( (clazz = classes[j++]) ) { 8384 // Remove *all* instances 8385 while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { 8386 cur = cur.replace( " " + clazz + " ", " " ); 8387 } 8388 } 8389 8390 // only assign if different to avoid unneeded rendering. 8391 finalValue = value ? jQuery.trim( cur ) : ""; 8392 if ( elem.className !== finalValue ) { 8393 elem.className = finalValue; 8394 } 8395 } 8396 } 8397 } 8398 8399 return this; 8400 }, 8401 8402 toggleClass: function( value, stateVal ) { 8403 var type = typeof value; 8404 8405 if ( typeof stateVal === "boolean" && type === "string" ) { 8406 return stateVal ? this.addClass( value ) : this.removeClass( value ); 8407 } 8408 8409 if ( jQuery.isFunction( value ) ) { 8410 return this.each(function( i ) { 8411 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); 8412 }); 8413 } 8414 8415 return this.each(function() { 8416 if ( type === "string" ) { 8417 // toggle individual class names 8418 var className, 8419 i = 0, 8420 self = jQuery( this ), 8421 classNames = value.match( rnotwhite ) || []; 8422 8423 while ( (className = classNames[ i++ ]) ) { 8424 // check each className given, space separated list 8425 if ( self.hasClass( className ) ) { 8426 self.removeClass( className ); 8427 } else { 8428 self.addClass( className ); 8429 } 8430 } 8431 8432 // Toggle whole class name 8433 } else if ( type === strundefined || type === "boolean" ) { 8434 if ( this.className ) { 8435 // store className if set 8436 jQuery._data( this, "__className__", this.className ); 8437 } 8438 8439 // If the element has a class name or if we're passed "false", 8440 // then remove the whole classname (if there was one, the above saved it). 8441 // Otherwise bring back whatever was previously saved (if anything), 8442 // falling back to the empty string if nothing was stored. 8443 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; 8444 } 8445 }); 8446 }, 8447 8448 hasClass: function( selector ) { 8449 var className = " " + selector + " ", 8450 i = 0, 8451 l = this.length; 8452 for ( ; i < l; i++ ) { 8453 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { 8454 return true; 8455 } 8456 } 8457 8458 return false; 8459 } 8460}); 8461 8462 8463 8464 8465// Return jQuery for attributes-only inclusion 8466 8467 8468jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + 8469 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + 8470 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { 8471 8472 // Handle event binding 8473 jQuery.fn[ name ] = function( data, fn ) { 8474 return arguments.length > 0 ? 8475 this.on( name, null, data, fn ) : 8476 this.trigger( name ); 8477 }; 8478}); 8479 8480jQuery.fn.extend({ 8481 hover: function( fnOver, fnOut ) { 8482 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); 8483 }, 8484 8485 bind: function( types, data, fn ) { 8486 return this.on( types, null, data, fn ); 8487 }, 8488 unbind: function( types, fn ) { 8489 return this.off( types, null, fn ); 8490 }, 8491 8492 delegate: function( selector, types, data, fn ) { 8493 return this.on( types, selector, data, fn ); 8494 }, 8495 undelegate: function( selector, types, fn ) { 8496 // ( namespace ) or ( selector, types [, fn] ) 8497 return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); 8498 } 8499}); 8500 8501 8502var nonce = jQuery.now(); 8503 8504var rquery = (/\?/); 8505 8506 8507 8508var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g; 8509 8510jQuery.parseJSON = function( data ) { 8511 // Attempt to parse using the native JSON parser first 8512 if ( window.JSON && window.JSON.parse ) { 8513 // Support: Android 2.3 8514 // Workaround failure to string-cast null input 8515 return window.JSON.parse( data + "" ); 8516 } 8517 8518 var requireNonComma, 8519 depth = null, 8520 str = jQuery.trim( data + "" ); 8521 8522 // Guard against invalid (and possibly dangerous) input by ensuring that nothing remains 8523 // after removing valid tokens 8524 return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) { 8525 8526 // Force termination if we see a misplaced comma 8527 if ( requireNonComma && comma ) { 8528 depth = 0; 8529 } 8530 8531 // Perform no more replacements after returning to outermost depth 8532 if ( depth === 0 ) { 8533 return token; 8534 } 8535 8536 // Commas must not follow "[", "{", or "," 8537 requireNonComma = open || comma; 8538 8539 // Determine new depth 8540 // array/object open ("[" or "{"): depth += true - false (increment) 8541 // array/object close ("]" or "}"): depth += false - true (decrement) 8542 // other cases ("," or primitive): depth += true - true (numeric cast) 8543 depth += !close - !open; 8544 8545 // Remove this token 8546 return ""; 8547 }) ) ? 8548 ( Function( "return " + str ) )() : 8549 jQuery.error( "Invalid JSON: " + data ); 8550}; 8551 8552 8553// Cross-browser xml parsing 8554jQuery.parseXML = function( data ) { 8555 var xml, tmp; 8556 if ( !data || typeof data !== "string" ) { 8557 return null; 8558 } 8559 try { 8560 if ( window.DOMParser ) { // Standard 8561 tmp = new DOMParser(); 8562 xml = tmp.parseFromString( data, "text/xml" ); 8563 } else { // IE 8564 xml = new ActiveXObject( "Microsoft.XMLDOM" ); 8565 xml.async = "false"; 8566 xml.loadXML( data ); 8567 } 8568 } catch( e ) { 8569 xml = undefined; 8570 } 8571 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { 8572 jQuery.error( "Invalid XML: " + data ); 8573 } 8574 return xml; 8575}; 8576 8577 8578var 8579 // Document location 8580 ajaxLocParts, 8581 ajaxLocation, 8582 8583 rhash = /#.*$/, 8584 rts = /([?&])_=[^&]*/, 8585 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL 8586 // #7653, #8125, #8152: local protocol detection 8587 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, 8588 rnoContent = /^(?:GET|HEAD)$/, 8589 rprotocol = /^\/\//, 8590 rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/, 8591 8592 /* Prefilters 8593 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) 8594 * 2) These are called: 8595 * - BEFORE asking for a transport 8596 * - AFTER param serialization (s.data is a string if s.processData is true) 8597 * 3) key is the dataType 8598 * 4) the catchall symbol "*" can be used 8599 * 5) execution will start with transport dataType and THEN continue down to "*" if needed 8600 */ 8601 prefilters = {}, 8602 8603 /* Transports bindings 8604 * 1) key is the dataType 8605 * 2) the catchall symbol "*" can be used 8606 * 3) selection will start with transport dataType and THEN go to "*" if needed 8607 */ 8608 transports = {}, 8609 8610 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression 8611 allTypes = "*/".concat("*"); 8612 8613// #8138, IE may throw an exception when accessing 8614// a field from window.location if document.domain has been set 8615try { 8616 ajaxLocation = location.href; 8617} catch( e ) { 8618 // Use the href attribute of an A element 8619 // since IE will modify it given document.location 8620 ajaxLocation = document.createElement( "a" ); 8621 ajaxLocation.href = ""; 8622 ajaxLocation = ajaxLocation.href; 8623} 8624 8625// Segment location into parts 8626ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; 8627 8628// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport 8629function addToPrefiltersOrTransports( structure ) { 8630 8631 // dataTypeExpression is optional and defaults to "*" 8632 return function( dataTypeExpression, func ) { 8633 8634 if ( typeof dataTypeExpression !== "string" ) { 8635 func = dataTypeExpression; 8636 dataTypeExpression = "*"; 8637 } 8638 8639 var dataType, 8640 i = 0, 8641 dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || []; 8642 8643 if ( jQuery.isFunction( func ) ) { 8644 // For each dataType in the dataTypeExpression 8645 while ( (dataType = dataTypes[i++]) ) { 8646 // Prepend if requested 8647 if ( dataType.charAt( 0 ) === "+" ) { 8648 dataType = dataType.slice( 1 ) || "*"; 8649 (structure[ dataType ] = structure[ dataType ] || []).unshift( func ); 8650 8651 // Otherwise append 8652 } else { 8653 (structure[ dataType ] = structure[ dataType ] || []).push( func ); 8654 } 8655 } 8656 } 8657 }; 8658} 8659 8660// Base inspection function for prefilters and transports 8661function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { 8662 8663 var inspected = {}, 8664 seekingTransport = ( structure === transports ); 8665 8666 function inspect( dataType ) { 8667 var selected; 8668 inspected[ dataType ] = true; 8669 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { 8670 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); 8671 if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { 8672 options.dataTypes.unshift( dataTypeOrTransport ); 8673 inspect( dataTypeOrTransport ); 8674 return false; 8675 } else if ( seekingTransport ) { 8676 return !( selected = dataTypeOrTransport ); 8677 } 8678 }); 8679 return selected; 8680 } 8681 8682 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); 8683} 8684 8685// A special extend for ajax options 8686// that takes "flat" options (not to be deep extended) 8687// Fixes #9887 8688function ajaxExtend( target, src ) { 8689 var deep, key, 8690 flatOptions = jQuery.ajaxSettings.flatOptions || {}; 8691 8692 for ( key in src ) { 8693 if ( src[ key ] !== undefined ) { 8694 ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ]; 8695 } 8696 } 8697 if ( deep ) { 8698 jQuery.extend( true, target, deep ); 8699 } 8700 8701 return target; 8702} 8703 8704/* Handles responses to an ajax request: 8705 * - finds the right dataType (mediates between content-type and expected dataType) 8706 * - returns the corresponding response 8707 */ 8708function ajaxHandleResponses( s, jqXHR, responses ) { 8709 var firstDataType, ct, finalDataType, type, 8710 contents = s.contents, 8711 dataTypes = s.dataTypes; 8712 8713 // Remove auto dataType and get content-type in the process 8714 while ( dataTypes[ 0 ] === "*" ) { 8715 dataTypes.shift(); 8716 if ( ct === undefined ) { 8717 ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); 8718 } 8719 } 8720 8721 // Check if we're dealing with a known content-type 8722 if ( ct ) { 8723 for ( type in contents ) { 8724 if ( contents[ type ] && contents[ type ].test( ct ) ) { 8725 dataTypes.unshift( type ); 8726 break; 8727 } 8728 } 8729 } 8730 8731 // Check to see if we have a response for the expected dataType 8732 if ( dataTypes[ 0 ] in responses ) { 8733 finalDataType = dataTypes[ 0 ]; 8734 } else { 8735 // Try convertible dataTypes 8736 for ( type in responses ) { 8737 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { 8738 finalDataType = type; 8739 break; 8740 } 8741 if ( !firstDataType ) { 8742 firstDataType = type; 8743 } 8744 } 8745 // Or just use first one 8746 finalDataType = finalDataType || firstDataType; 8747 } 8748 8749 // If we found a dataType 8750 // We add the dataType to the list if needed 8751 // and return the corresponding response 8752 if ( finalDataType ) { 8753 if ( finalDataType !== dataTypes[ 0 ] ) { 8754 dataTypes.unshift( finalDataType ); 8755 } 8756 return responses[ finalDataType ]; 8757 } 8758} 8759 8760/* Chain conversions given the request and the original response 8761 * Also sets the responseXXX fields on the jqXHR instance 8762 */ 8763function ajaxConvert( s, response, jqXHR, isSuccess ) { 8764 var conv2, current, conv, tmp, prev, 8765 converters = {}, 8766 // Work with a copy of dataTypes in case we need to modify it for conversion 8767 dataTypes = s.dataTypes.slice(); 8768 8769 // Create converters map with lowercased keys 8770 if ( dataTypes[ 1 ] ) { 8771 for ( conv in s.converters ) { 8772 converters[ conv.toLowerCase() ] = s.converters[ conv ]; 8773 } 8774 } 8775 8776 current = dataTypes.shift(); 8777 8778 // Convert to each sequential dataType 8779 while ( current ) { 8780 8781 if ( s.responseFields[ current ] ) { 8782 jqXHR[ s.responseFields[ current ] ] = response; 8783 } 8784 8785 // Apply the dataFilter if provided 8786 if ( !prev && isSuccess && s.dataFilter ) { 8787 response = s.dataFilter( response, s.dataType ); 8788 } 8789 8790 prev = current; 8791 current = dataTypes.shift(); 8792 8793 if ( current ) { 8794 8795 // There's only work to do if current dataType is non-auto 8796 if ( current === "*" ) { 8797 8798 current = prev; 8799 8800 // Convert response if prev dataType is non-auto and differs from current 8801 } else if ( prev !== "*" && prev !== current ) { 8802 8803 // Seek a direct converter 8804 conv = converters[ prev + " " + current ] || converters[ "* " + current ]; 8805 8806 // If none found, seek a pair 8807 if ( !conv ) { 8808 for ( conv2 in converters ) { 8809 8810 // If conv2 outputs current 8811 tmp = conv2.split( " " ); 8812 if ( tmp[ 1 ] === current ) { 8813 8814 // If prev can be converted to accepted input 8815 conv = converters[ prev + " " + tmp[ 0 ] ] || 8816 converters[ "* " + tmp[ 0 ] ]; 8817 if ( conv ) { 8818 // Condense equivalence converters 8819 if ( conv === true ) { 8820 conv = converters[ conv2 ]; 8821 8822 // Otherwise, insert the intermediate dataType 8823 } else if ( converters[ conv2 ] !== true ) { 8824 current = tmp[ 0 ]; 8825 dataTypes.unshift( tmp[ 1 ] ); 8826 } 8827 break; 8828 } 8829 } 8830 } 8831 } 8832 8833 // Apply converter (if not an equivalence) 8834 if ( conv !== true ) { 8835 8836 // Unless errors are allowed to bubble, catch and return them 8837 if ( conv && s[ "throws" ] ) { 8838 response = conv( response ); 8839 } else { 8840 try { 8841 response = conv( response ); 8842 } catch ( e ) { 8843 return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; 8844 } 8845 } 8846 } 8847 } 8848 } 8849 } 8850 8851 return { state: "success", data: response }; 8852} 8853 8854jQuery.extend({ 8855 8856 // Counter for holding the number of active queries 8857 active: 0, 8858 8859 // Last-Modified header cache for next request 8860 lastModified: {}, 8861 etag: {}, 8862 8863 ajaxSettings: { 8864 url: ajaxLocation, 8865 type: "GET", 8866 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), 8867 global: true, 8868 processData: true, 8869 async: true, 8870 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 8871 /* 8872 timeout: 0, 8873 data: null, 8874 dataType: null, 8875 username: null, 8876 password: null, 8877 cache: null, 8878 throws: false, 8879 traditional: false, 8880 headers: {}, 8881 */ 8882 8883 accepts: { 8884 "*": allTypes, 8885 text: "text/plain", 8886 html: "text/html", 8887 xml: "application/xml, text/xml", 8888 json: "application/json, text/javascript" 8889 }, 8890 8891 contents: { 8892 xml: /xml/, 8893 html: /html/, 8894 json: /json/ 8895 }, 8896 8897 responseFields: { 8898 xml: "responseXML", 8899 text: "responseText", 8900 json: "responseJSON" 8901 }, 8902 8903 // Data converters 8904 // Keys separate source (or catchall "*") and destination types with a single space 8905 converters: { 8906 8907 // Convert anything to text 8908 "* text": String, 8909 8910 // Text to html (true = no transformation) 8911 "text html": true, 8912 8913 // Evaluate text as a json expression 8914 "text json": jQuery.parseJSON, 8915 8916 // Parse text as xml 8917 "text xml": jQuery.parseXML 8918 }, 8919 8920 // For options that shouldn't be deep extended: 8921 // you can add your own custom options here if 8922 // and when you create one that shouldn't be 8923 // deep extended (see ajaxExtend) 8924 flatOptions: { 8925 url: true, 8926 context: true 8927 } 8928 }, 8929 8930 // Creates a full fledged settings object into target 8931 // with both ajaxSettings and settings fields. 8932 // If target is omitted, writes into ajaxSettings. 8933 ajaxSetup: function( target, settings ) { 8934 return settings ? 8935 8936 // Building a settings object 8937 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : 8938 8939 // Extending ajaxSettings 8940 ajaxExtend( jQuery.ajaxSettings, target ); 8941 }, 8942 8943 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), 8944 ajaxTransport: addToPrefiltersOrTransports( transports ), 8945 8946 // Main method 8947 ajax: function( url, options ) { 8948 8949 // If url is an object, simulate pre-1.5 signature 8950 if ( typeof url === "object" ) { 8951 options = url; 8952 url = undefined; 8953 } 8954 8955 // Force options to be an object 8956 options = options || {}; 8957 8958 var // Cross-domain detection vars 8959 parts, 8960 // Loop variable 8961 i, 8962 // URL without anti-cache param 8963 cacheURL, 8964 // Response headers as string 8965 responseHeadersString, 8966 // timeout handle 8967 timeoutTimer, 8968 8969 // To know if global events are to be dispatched 8970 fireGlobals, 8971 8972 transport, 8973 // Response headers 8974 responseHeaders, 8975 // Create the final options object 8976 s = jQuery.ajaxSetup( {}, options ), 8977 // Callbacks context 8978 callbackContext = s.context || s, 8979 // Context for global events is callbackContext if it is a DOM node or jQuery collection 8980 globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? 8981 jQuery( callbackContext ) : 8982 jQuery.event, 8983 // Deferreds 8984 deferred = jQuery.Deferred(), 8985 completeDeferred = jQuery.Callbacks("once memory"), 8986 // Status-dependent callbacks 8987 statusCode = s.statusCode || {}, 8988 // Headers (they are sent all at once) 8989 requestHeaders = {}, 8990 requestHeadersNames = {}, 8991 // The jqXHR state 8992 state = 0, 8993 // Default abort message 8994 strAbort = "canceled", 8995 // Fake xhr 8996 jqXHR = { 8997 readyState: 0, 8998 8999 // Builds headers hashtable if needed 9000 getResponseHeader: function( key ) { 9001 var match; 9002 if ( state === 2 ) { 9003 if ( !responseHeaders ) { 9004 responseHeaders = {}; 9005 while ( (match = rheaders.exec( responseHeadersString )) ) { 9006 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; 9007 } 9008 } 9009 match = responseHeaders[ key.toLowerCase() ]; 9010 } 9011 return match == null ? null : match; 9012 }, 9013 9014 // Raw string 9015 getAllResponseHeaders: function() { 9016 return state === 2 ? responseHeadersString : null; 9017 }, 9018 9019 // Caches the header 9020 setRequestHeader: function( name, value ) { 9021 var lname = name.toLowerCase(); 9022 if ( !state ) { 9023 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; 9024 requestHeaders[ name ] = value; 9025 } 9026 return this; 9027 }, 9028 9029 // Overrides response content-type header 9030 overrideMimeType: function( type ) { 9031 if ( !state ) { 9032 s.mimeType = type; 9033 } 9034 return this; 9035 }, 9036 9037 // Status-dependent callbacks 9038 statusCode: function( map ) { 9039 var code; 9040 if ( map ) { 9041 if ( state < 2 ) { 9042 for ( code in map ) { 9043 // Lazy-add the new callback in a way that preserves old ones 9044 statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; 9045 } 9046 } else { 9047 // Execute the appropriate callbacks 9048 jqXHR.always( map[ jqXHR.status ] ); 9049 } 9050 } 9051 return this; 9052 }, 9053 9054 // Cancel the request 9055 abort: function( statusText ) { 9056 var finalText = statusText || strAbort; 9057 if ( transport ) { 9058 transport.abort( finalText ); 9059 } 9060 done( 0, finalText ); 9061 return this; 9062 } 9063 }; 9064 9065 // Attach deferreds 9066 deferred.promise( jqXHR ).complete = completeDeferred.add; 9067 jqXHR.success = jqXHR.done; 9068 jqXHR.error = jqXHR.fail; 9069 9070 // Remove hash character (#7531: and string promotion) 9071 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) 9072 // Handle falsy url in the settings object (#10093: consistency with old signature) 9073 // We also use the url parameter if available 9074 s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); 9075 9076 // Alias method option to type as per ticket #12004 9077 s.type = options.method || options.type || s.method || s.type; 9078 9079 // Extract dataTypes list 9080 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ]; 9081 9082 // A cross-domain request is in order when we have a protocol:host:port mismatch 9083 if ( s.crossDomain == null ) { 9084 parts = rurl.exec( s.url.toLowerCase() ); 9085 s.crossDomain = !!( parts && 9086 ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || 9087 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !== 9088 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) ) 9089 ); 9090 } 9091 9092 // Convert data if not already a string 9093 if ( s.data && s.processData && typeof s.data !== "string" ) { 9094 s.data = jQuery.param( s.data, s.traditional ); 9095 } 9096 9097 // Apply prefilters 9098 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); 9099 9100 // If request was aborted inside a prefilter, stop there 9101 if ( state === 2 ) { 9102 return jqXHR; 9103 } 9104 9105 // We can fire global events as of now if asked to 9106
9106// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) 9107 fireGlobals = jQuery.event && s.global; 9108 9109 // Watch for a new set of requests 9110 if ( fireGlobals && jQuery.active++ === 0 ) { 9111 jQuery.event.trigger("ajaxStart"); 9112 } 9113 9114 // Uppercase the type 9115 s.type = s.type.toUpperCase(); 9116 9117 // Determine if request has content 9118 s.hasContent = !rnoContent.test( s.type ); 9119 9120 // Save the URL in case we're toying with the If-Modified-Since 9121 // and/or If-None-Match header later on 9122 cacheURL = s.url; 9123 9124 // More options handling for requests with no content 9125 if ( !s.hasContent ) { 9126 9127 // If data is available, append data to url 9128 if ( s.data ) {
vendor: 12,323 bytes, lines 9129-9593
9129 cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); 9130 // #9682: remove data so that it's not used in an eventual retry 9131 delete s.data; 9132 } 9133 9134 // Add anti-cache in url if needed 9135 if ( s.cache === false ) { 9136 s.url = rts.test( cacheURL ) ? 9137 9138 // If there is already a '_' parameter, set its value 9139 cacheURL.replace( rts, "$1_=" + nonce++ ) : 9140 9141 // Otherwise add one to the end 9142 cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++; 9143 } 9144 } 9145 9146 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 9147 if ( s.ifModified ) { 9148 if ( jQuery.lastModified[ cacheURL ] ) { 9149 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); 9150 } 9151 if ( jQuery.etag[ cacheURL ] ) { 9152 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); 9153 } 9154 } 9155 9156 // Set the correct header, if data is being sent 9157 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { 9158 jqXHR.setRequestHeader( "Content-Type", s.contentType ); 9159 } 9160 9161 // Set the Accepts header for the server, depending on the dataType 9162 jqXHR.setRequestHeader( 9163 "Accept", 9164 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? 9165 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : 9166 s.accepts[ "*" ] 9167 ); 9168 9169 // Check for headers option 9170 for ( i in s.headers ) { 9171 jqXHR.setRequestHeader( i, s.headers[ i ] ); 9172 } 9173 9174 // Allow custom headers/mimetypes and early abort 9175 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { 9176 // Abort if not done already and return 9177 return jqXHR.abort(); 9178 } 9179 9180 // aborting is no longer a cancellation 9181 strAbort = "abort"; 9182 9183 // Install callbacks on deferreds 9184 for ( i in { success: 1, error: 1, complete: 1 } ) { 9185 jqXHR[ i ]( s[ i ] ); 9186 } 9187 9188 // Get transport 9189 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); 9190 9191 // If no transport, we auto-abort 9192 if ( !transport ) { 9193 done( -1, "No Transport" ); 9194 } else { 9195 jqXHR.readyState = 1; 9196 9197 // Send global event 9198 if ( fireGlobals ) { 9199 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); 9200 } 9201 // Timeout 9202 if ( s.async && s.timeout > 0 ) { 9203 timeoutTimer = setTimeout(function() { 9204 jqXHR.abort("timeout"); 9205 }, s.timeout ); 9206 } 9207 9208 try { 9209 state = 1; 9210 transport.send( requestHeaders, done ); 9211 } catch ( e ) { 9212 // Propagate exception as error if not done 9213 if ( state < 2 ) { 9214 done( -1, e ); 9215 // Simply rethrow otherwise 9216 } else { 9217 throw e; 9218 } 9219 } 9220 } 9221 9222 // Callback for when everything is done 9223 function done( status, nativeStatusText, responses, headers ) { 9224 var isSuccess, success, error, response, modified, 9225 statusText = nativeStatusText; 9226 9227 // Called once 9228 if ( state === 2 ) { 9229 return; 9230 } 9231 9232 // State is "done" now 9233 state = 2; 9234 9235 // Clear timeout if it exists 9236 if ( timeoutTimer ) { 9237 clearTimeout( timeoutTimer ); 9238 } 9239 9240 // Dereference transport for early garbage collection 9241 // (no matter how long the jqXHR object will be used) 9242 transport = undefined; 9243 9244 // Cache response headers 9245 responseHeadersString = headers || ""; 9246 9247 // Set readyState 9248 jqXHR.readyState = status > 0 ? 4 : 0; 9249 9250 // Determine if successful 9251 isSuccess = status >= 200 && status < 300 || status === 304; 9252 9253 // Get response data 9254 if ( responses ) { 9255 response = ajaxHandleResponses( s, jqXHR, responses ); 9256 } 9257 9258 // Convert no matter what (that way responseXXX fields are always set) 9259 response = ajaxConvert( s, response, jqXHR, isSuccess ); 9260 9261 // If successful, handle type chaining 9262 if ( isSuccess ) { 9263 9264 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 9265 if ( s.ifModified ) { 9266 modified = jqXHR.getResponseHeader("Last-Modified"); 9267 if ( modified ) { 9268 jQuery.lastModified[ cacheURL ] = modified; 9269 } 9270 modified = jqXHR.getResponseHeader("etag"); 9271 if ( modified ) { 9272 jQuery.etag[ cacheURL ] = modified; 9273 } 9274 } 9275 9276 // if no content 9277 if ( status === 204 || s.type === "HEAD" ) { 9278 statusText = "nocontent"; 9279 9280 // if not modified 9281 } else if ( status === 304 ) { 9282 statusText = "notmodified"; 9283 9284 // If we have data, let's convert it 9285 } else { 9286 statusText = response.state; 9287 success = response.data; 9288 error = response.error; 9289 isSuccess = !error; 9290 } 9291 } else { 9292 // We extract error from statusText 9293 // then normalize statusText and status for non-aborts 9294 error = statusText; 9295 if ( status || !statusText ) { 9296 statusText = "error"; 9297 if ( status < 0 ) { 9298 status = 0; 9299 } 9300 } 9301 } 9302 9303 // Set data for the fake xhr object 9304 jqXHR.status = status; 9305 jqXHR.statusText = ( nativeStatusText || statusText ) + ""; 9306 9307 // Success/Error 9308 if ( isSuccess ) { 9309 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); 9310 } else { 9311 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); 9312 } 9313 9314 // Status-dependent callbacks 9315 jqXHR.statusCode( statusCode ); 9316 statusCode = undefined; 9317 9318 if ( fireGlobals ) { 9319 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", 9320 [ jqXHR, s, isSuccess ? success : error ] ); 9321 } 9322 9323 // Complete 9324 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); 9325 9326 if ( fireGlobals ) { 9327 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); 9328 // Handle the global AJAX counter 9329 if ( !( --jQuery.active ) ) { 9330 jQuery.event.trigger("ajaxStop"); 9331 } 9332 } 9333 } 9334 9335 return jqXHR; 9336 }, 9337 9338 getJSON: function( url, data, callback ) { 9339 return jQuery.get( url, data, callback, "json" ); 9340 }, 9341 9342 getScript: function( url, callback ) { 9343 return jQuery.get( url, undefined, callback, "script" ); 9344 } 9345}); 9346 9347jQuery.each( [ "get", "post" ], function( i, method ) { 9348 jQuery[ method ] = function( url, data, callback, type ) { 9349 // shift arguments if data argument was omitted 9350 if ( jQuery.isFunction( data ) ) { 9351 type = type || callback; 9352 callback = data; 9353 data = undefined; 9354 } 9355 9356 return jQuery.ajax({ 9357 url: url, 9358 type: method, 9359 dataType: type, 9360 data: data, 9361 success: callback 9362 }); 9363 }; 9364}); 9365 9366 9367jQuery._evalUrl = function( url ) { 9368 return jQuery.ajax({ 9369 url: url, 9370 type: "GET", 9371 dataType: "script", 9372 async: false, 9373 global: false, 9374 "throws": true 9375 }); 9376}; 9377 9378 9379jQuery.fn.extend({ 9380 wrapAll: function( html ) { 9381 if ( jQuery.isFunction( html ) ) { 9382 return this.each(function(i) { 9383 jQuery(this).wrapAll( html.call(this, i) ); 9384 }); 9385 } 9386 9387 if ( this[0] ) { 9388 // The elements to wrap the target around 9389 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); 9390 9391 if ( this[0].parentNode ) { 9392 wrap.insertBefore( this[0] ); 9393 } 9394 9395 wrap.map(function() { 9396 var elem = this; 9397 9398 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { 9399 elem = elem.firstChild; 9400 } 9401 9402 return elem; 9403 }).append( this ); 9404 } 9405 9406 return this; 9407 }, 9408 9409 wrapInner: function( html ) { 9410 if ( jQuery.isFunction( html ) ) { 9411 return this.each(function(i) { 9412 jQuery(this).wrapInner( html.call(this, i) ); 9413 }); 9414 } 9415 9416 return this.each(function() { 9417 var self = jQuery( this ), 9418 contents = self.contents(); 9419 9420 if ( contents.length ) { 9421 contents.wrapAll( html ); 9422 9423 } else { 9424 self.append( html ); 9425 } 9426 }); 9427 }, 9428 9429 wrap: function( html ) { 9430 var isFunction = jQuery.isFunction( html ); 9431 9432 return this.each(function(i) { 9433 jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); 9434 }); 9435 }, 9436 9437 unwrap: function() { 9438 return this.parent().each(function() { 9439 if ( !jQuery.nodeName( this, "body" ) ) { 9440 jQuery( this ).replaceWith( this.childNodes ); 9441 } 9442 }).end(); 9443 } 9444}); 9445 9446 9447jQuery.expr.filters.hidden = function( elem ) { 9448 // Support: Opera <= 12.12 9449 // Opera reports offsetWidths and offsetHeights less than zero on some elements 9450 return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 || 9451 (!support.reliableHiddenOffsets() && 9452 ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none"); 9453}; 9454 9455jQuery.expr.filters.visible = function( elem ) { 9456 return !jQuery.expr.filters.hidden( elem ); 9457}; 9458 9459 9460 9461 9462var r20 = /%20/g, 9463 rbracket = /\[\]$/, 9464 rCRLF = /\r?\n/g, 9465 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, 9466 rsubmittable = /^(?:input|select|textarea|keygen)/i; 9467 9468function buildParams( prefix, obj, traditional, add ) { 9469 var name; 9470 9471 if ( jQuery.isArray( obj ) ) { 9472 // Serialize array item. 9473 jQuery.each( obj, function( i, v ) { 9474 if ( traditional || rbracket.test( prefix ) ) { 9475 // Treat each array item as a scalar. 9476 add( prefix, v ); 9477 9478 } else { 9479 // Item is non-scalar (array or object), encode its numeric index. 9480 buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); 9481 } 9482 }); 9483 9484 } else if ( !traditional && jQuery.type( obj ) === "object" ) { 9485 // Serialize object item. 9486 for ( name in obj ) { 9487 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); 9488 } 9489 9490 } else { 9491 // Serialize scalar item. 9492 add( prefix, obj ); 9493 } 9494} 9495 9496// Serialize an array of form elements or a set of 9497// key/values into a query string 9498jQuery.param = function( a, traditional ) { 9499 var prefix, 9500 s = [], 9501 add = function( key, value ) { 9502 // If value is a function, invoke it and return its value 9503 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); 9504 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); 9505 }; 9506 9507 // Set traditional to true for jQuery <= 1.3.2 behavior. 9508 if ( traditional === undefined ) { 9509 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; 9510 } 9511 9512 // If an array was passed in, assume that it is an array of form elements. 9513 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { 9514 // Serialize the form elements 9515 jQuery.each( a, function() { 9516 add( this.name, this.value ); 9517 }); 9518 9519 } else { 9520 // If traditional, encode the "old" way (the way 1.3.2 or older 9521 // did it), otherwise encode params recursively. 9522 for ( prefix in a ) { 9523 buildParams( prefix, a[ prefix ], traditional, add ); 9524 } 9525 } 9526 9527 // Return the resulting serialization 9528 return s.join( "&" ).replace( r20, "+" ); 9529}; 9530 9531jQuery.fn.extend({ 9532 serialize: function() { 9533 return jQuery.param( this.serializeArray() ); 9534 }, 9535 serializeArray: function() { 9536 return this.map(function() { 9537 // Can add propHook for "elements" to filter or add form elements 9538 var elements = jQuery.prop( this, "elements" ); 9539 return elements ? jQuery.makeArray( elements ) : this; 9540 }) 9541 .filter(function() { 9542 var type = this.type; 9543 // Use .is(":disabled") so that fieldset[disabled] works 9544 return this.name && !jQuery( this ).is( ":disabled" ) && 9545 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && 9546 ( this.checked || !rcheckableType.test( type ) ); 9547 }) 9548 .map(function( i, elem ) { 9549 var val = jQuery( this ).val(); 9550 9551 return val == null ? 9552 null : 9553 jQuery.isArray( val ) ? 9554 jQuery.map( val, function( val ) { 9555 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 9556 }) : 9557 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 9558 }).get(); 9559 } 9560}); 9561 9562 9563// Create the request object 9564// (This is still attached to ajaxSettings for backward compatibility) 9565jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ? 9566 // Support: IE6+ 9567 function() { 9568 9569 // XHR cannot access local files, always use ActiveX for that case 9570 return !this.isLocal && 9571 9572 // Support: IE7-8 9573 // oldIE XHR does not support non-RFC2616 methods (#13240) 9574 // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx 9575 // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9 9576 // Although this check for six methods instead of eight 9577 // since IE also does not support "trace" and "connect" 9578 /^(get|post|head|put|delete|options)$/i.test( this.type ) && 9579 9580 createStandardXHR() || createActiveXHR(); 9581 } : 9582 // For all other browsers, use the standard XMLHttpRequest object 9583 createStandardXHR; 9584 9585var xhrId = 0, 9586 xhrCallbacks = {}, 9587 xhrSupported = jQuery.ajaxSettings.xhr(); 9588 9589// Support: IE<10 9590// Open requests must be manually aborted on unload (#5280) 9591// See https://support.microsoft.com/kb/2856746 for more info 9592if ( window.attachEvent ) { 9593 window.attachEvent( "on
vendor: 11,251 bytes, lines 9593-10026
9593unload", function() { 9594 for ( var key in xhrCallbacks ) { 9595 xhrCallbacks[ key ]( undefined, true ); 9596 } 9597 }); 9598} 9599 9600// Determine support properties 9601support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); 9602xhrSupported = support.ajax = !!xhrSupported; 9603 9604// Create transport if the browser can provide an xhr 9605if ( xhrSupported ) { 9606 9607 jQuery.ajaxTransport(function( options ) { 9608 // Cross domain only allowed if supported through XMLHttpRequest 9609 if ( !options.crossDomain || support.cors ) { 9610 9611 var callback; 9612 9613 return { 9614 send: function( headers, complete ) { 9615 var i, 9616 xhr = options.xhr(), 9617 id = ++xhrId; 9618 9619 // Open the socket 9620 xhr.open( options.type, options.url, options.async, options.username, options.password ); 9621 9622 // Apply custom fields if provided 9623 if ( options.xhrFields ) { 9624 for ( i in options.xhrFields ) { 9625 xhr[ i ] = options.xhrFields[ i ]; 9626 } 9627 } 9628 9629 // Override mime type if needed 9630 if ( options.mimeType && xhr.overrideMimeType ) { 9631 xhr.overrideMimeType( options.mimeType ); 9632 } 9633 9634 // X-Requested-With header 9635 // For cross-domain requests, seeing as conditions for a preflight are 9636 // akin to a jigsaw puzzle, we simply never set it to be sure. 9637 // (it can always be set on a per-request basis or even using ajaxSetup) 9638 // For same-domain requests, won't change header if already provided. 9639 if ( !options.crossDomain && !headers["X-Requested-With"] ) { 9640 headers["X-Requested-With"] = "XMLHttpRequest"; 9641 } 9642 9643 // Set headers 9644 for ( i in headers ) { 9645 // Support: IE<9 9646 // IE's ActiveXObject throws a 'Type Mismatch' exception when setting 9647 // request header to a null-value. 9648 // 9649 // To keep consistent with other XHR implementations, cast the value 9650 // to string and ignore `undefined`. 9651 if ( headers[ i ] !== undefined ) { 9652 xhr.setRequestHeader( i, headers[ i ] + "" ); 9653 } 9654 } 9655 9656 // Do send the request 9657 // This may raise an exception which is actually 9658 // handled in jQuery.ajax (so no try/catch here) 9659 xhr.send( ( options.hasContent && options.data ) || null ); 9660 9661 // Listener 9662 callback = function( _, isAbort ) { 9663 var status, statusText, responses; 9664 9665 // Was never called and is aborted or complete 9666 if ( callback && ( isAbort || xhr.readyState === 4 ) ) { 9667 // Clean up 9668 delete xhrCallbacks[ id ]; 9669 callback = undefined; 9670 xhr.onreadystatechange = jQuery.noop; 9671 9672 // Abort manually if needed 9673 if ( isAbort ) { 9674 if ( xhr.readyState !== 4 ) { 9675 xhr.abort(); 9676 } 9677 } else { 9678 responses = {}; 9679 status = xhr.status; 9680 9681 // Support: IE<10 9682 // Accessing binary-data responseText throws an exception 9683 // (#11426) 9684 if ( typeof xhr.responseText === "string" ) { 9685 responses.text = xhr.responseText; 9686 } 9687 9688 // Firefox throws an exception when accessing 9689 // statusText for faulty cross-domain requests 9690 try { 9691 statusText = xhr.statusText; 9692 } catch( e ) { 9693 // We normalize with Webkit giving an empty statusText 9694 statusText = ""; 9695 } 9696 9697 // Filter status for non standard behaviors 9698 9699 // If the request is local and we have data: assume a success 9700 // (success with no data won't get notified, that's the best we 9701 // can do given current implementations) 9702 if ( !status && options.isLocal && !options.crossDomain ) { 9703 status = responses.text ? 200 : 404; 9704 // IE - #1450: sometimes returns 1223 when it should be 204 9705 } else if ( status === 1223 ) { 9706 status = 204; 9707 } 9708 } 9709 } 9710 9711 // Call complete if needed 9712 if ( responses ) { 9713 complete( status, statusText, responses, xhr.getAllResponseHeaders() ); 9714 } 9715 }; 9716 9717 if ( !options.async ) { 9718 // if we're in sync mode we fire the callback 9719 callback(); 9720 } else if ( xhr.readyState === 4 ) { 9721 // (IE6 & IE7) if it's in cache and has been 9722 // retrieved directly we need to fire the callback 9723 setTimeout( callback ); 9724 } else { 9725 // Add to the list of active xhr callbacks 9726 xhr.onreadystatechange = xhrCallbacks[ id ] = callback; 9727 } 9728 }, 9729 9730 abort: function() { 9731 if ( callback ) { 9732 callback( undefined, true ); 9733 } 9734 } 9735 }; 9736 } 9737 }); 9738} 9739 9740// Functions to create xhrs 9741function createStandardXHR() { 9742 try { 9743 return new window.XMLHttpRequest(); 9744 } catch( e ) {} 9745} 9746 9747function createActiveXHR() { 9748 try { 9749 return new window.ActiveXObject( "Microsoft.XMLHTTP" ); 9750 } catch( e ) {} 9751} 9752 9753 9754 9755 9756// Install script dataType 9757jQuery.ajaxSetup({ 9758 accepts: { 9759 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" 9760 }, 9761 contents: { 9762 script: /(?:java|ecma)script/ 9763 }, 9764 converters: { 9765 "text script": function( text ) { 9766 jQuery.globalEval( text ); 9767 return text; 9768 } 9769 } 9770}); 9771 9772// Handle cache's special case and global 9773jQuery.ajaxPrefilter( "script", function( s ) { 9774 if ( s.cache === undefined ) { 9775 s.cache = false; 9776 } 9777 if ( s.crossDomain ) { 9778 s.type = "GET"; 9779 s.global = false; 9780 } 9781}); 9782 9783// Bind script tag hack transport 9784jQuery.ajaxTransport( "script", function(s) { 9785 9786 // This transport only deals with cross domain requests 9787 if ( s.crossDomain ) { 9788 9789 var script, 9790 head = document.head || jQuery("head")[0] || document.documentElement; 9791 9792 return { 9793 9794 send: function( _, callback ) { 9795 9796 script = document.createElement("script"); 9797 9798 script.async = true; 9799 9800 if ( s.scriptCharset ) { 9801 script.charset = s.scriptCharset; 9802 } 9803 9804 script.src = s.url; 9805 9806 // Attach handlers for all browsers 9807 script.onload = script.onreadystatechange = function( _, isAbort ) { 9808 9809 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) { 9810 9811 // Handle memory leak in IE 9812 script.onload = script.onreadystatechange = null; 9813 9814 // Remove the script 9815 if ( script.parentNode ) { 9816 script.parentNode.removeChild( script ); 9817 } 9818 9819 // Dereference the script 9820 script = null; 9821 9822 // Callback if not abort 9823 if ( !isAbort ) { 9824 callback( 200, "success" ); 9825 } 9826 } 9827 }; 9828 9829 // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending 9830 // Use native DOM manipulation to avoid our domManip AJAX trickery 9831 head.insertBefore( script, head.firstChild ); 9832 }, 9833 9834 abort: function() { 9835 if ( script ) { 9836 script.onload( undefined, true ); 9837 } 9838 } 9839 }; 9840 } 9841}); 9842 9843 9844 9845 9846var oldCallbacks = [], 9847 rjsonp = /(=)\?(?=&|$)|\?\?/; 9848 9849// Default jsonp settings 9850jQuery.ajaxSetup({ 9851 jsonp: "callback", 9852 jsonpCallback: function() { 9853 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); 9854 this[ callback ] = true; 9855 return callback; 9856 } 9857}); 9858 9859// Detect, normalize options and install callbacks for jsonp requests 9860jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { 9861 9862 var callbackName, overwritten, responseContainer, 9863 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? 9864 "url" : 9865 typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" 9866 ); 9867 9868 // Handle iff the expected data type is "jsonp" or we have a parameter to set 9869 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { 9870 9871 // Get callback name, remembering preexisting value associated with it 9872 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? 9873 s.jsonpCallback() : 9874 s.jsonpCallback; 9875 9876 // Insert callback into url or form data 9877 if ( jsonProp ) { 9878 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); 9879 } else if ( s.jsonp !== false ) { 9880 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; 9881 } 9882 9883 // Use data converter to retrieve json after script execution 9884 s.converters["script json"] = function() { 9885 if ( !responseContainer ) { 9886 jQuery.error( callbackName + " was not called" ); 9887 } 9888 return responseContainer[ 0 ]; 9889 }; 9890 9891 // force json dataType 9892 s.dataTypes[ 0 ] = "json"; 9893 9894 // Install callback 9895 overwritten = window[ callbackName ]; 9896 window[ callbackName ] = function() { 9897 responseContainer = arguments; 9898 }; 9899 9900 // Clean-up function (fires after converters) 9901 jqXHR.always(function() { 9902 // Restore preexisting value 9903 window[ callbackName ] = overwritten; 9904 9905 // Save back as free 9906 if ( s[ callbackName ] ) { 9907 // make sure that re-using the options doesn't screw things around 9908 s.jsonpCallback = originalSettings.jsonpCallback; 9909 9910 // save the callback name for future use 9911 oldCallbacks.push( callbackName ); 9912 } 9913 9914 // Call if it was a function and we have a response 9915 if ( responseContainer && jQuery.isFunction( overwritten ) ) { 9916 overwritten( responseContainer[ 0 ] ); 9917 } 9918 9919 responseContainer = overwritten = undefined; 9920 }); 9921 9922 // Delegate to script 9923 return "script"; 9924 } 9925}); 9926 9927 9928 9929 9930// data: string of html 9931// context (optional): If specified, the fragment will be created in this context, defaults to document 9932// keepScripts (optional): If true, will include scripts passed in the html string 9933jQuery.parseHTML = function( data, context, keepScripts ) { 9934 if ( !data || typeof data !== "string" ) { 9935 return null; 9936 } 9937 if ( typeof context === "boolean" ) { 9938 keepScripts = context; 9939 context = false; 9940 } 9941 context = context || document; 9942 9943 var parsed = rsingleTag.exec( data ), 9944 scripts = !keepScripts && []; 9945 9946 // Single tag 9947 if ( parsed ) { 9948 return [ context.createElement( parsed[1] ) ]; 9949 } 9950 9951 parsed = jQuery.buildFragment( [ data ], context, scripts ); 9952 9953 if ( scripts && scripts.length ) { 9954 jQuery( scripts ).remove(); 9955 } 9956 9957 return jQuery.merge( [], parsed.childNodes ); 9958}; 9959 9960 9961// Keep a copy of the old load method 9962var _load = jQuery.fn.load; 9963 9964/** 9965 * Load a url into a page 9966 */ 9967jQuery.fn.load = function( url, params, callback ) { 9968 if ( typeof url !== "string" && _load ) { 9969 return _load.apply( this, arguments ); 9970 } 9971 9972 var selector, response, type, 9973 self = this, 9974 off = url.indexOf(" "); 9975 9976 if ( off >= 0 ) { 9977 selector = jQuery.trim( url.slice( off, url.length ) ); 9978 url = url.slice( 0, off ); 9979 } 9980 9981 // If it's a function 9982 if ( jQuery.isFunction( params ) ) { 9983 9984 // We assume that it's the callback 9985 callback = params; 9986 params = undefined; 9987 9988 // Otherwise, build a param string 9989 } else if ( params && typeof params === "object" ) { 9990 type = "POST"; 9991 } 9992 9993 // If we have elements to modify, make the request 9994 if ( self.length > 0 ) { 9995 jQuery.ajax({ 9996 url: url, 9997 9998 // if "type" variable is undefined, then "GET" method will be used 9999 type: type, 10000 dataType: "html", 10001 data: params 10002 }).done(function( responseText ) { 10003 10004 // Save response for use in complete callback 10005 response = arguments; 10006 10007 self.html( selector ? 10008 10009 // If a selector was specified, locate the right elements in a dummy div 10010 // Exclude scripts to avoid IE 'Permission Denied' errors 10011 jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) : 10012 10013 // Otherwise use the full result 10014 responseText ); 10015 10016 }).complete( callback && function( jqXHR, status ) { 10017 self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); 10018 }); 10019 } 10020 10021 return this; 10022}; 10023 10024 10025 10026
10027// Attach a bunch of functions for handling common AJAX events 10028jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) { 10029 jQuery.fn[ type ] = function( fn ) { 10030 return this.on( type, fn ); 10031 }; 10032})
vendor: 9,149 bytes, lines 10032-10346
10032; 10033 10034 10035 10036 10037jQuery.expr.filters.animated = function( elem ) { 10038 return jQuery.grep(jQuery.timers, function( fn ) { 10039 return elem === fn.elem; 10040 }).length; 10041}; 10042 10043 10044 10045 10046 10047var docElem = window.document.documentElement; 10048 10049/** 10050 * Gets a window from an element 10051 */ 10052function getWindow( elem ) { 10053 return jQuery.isWindow( elem ) ? 10054 elem : 10055 elem.nodeType === 9 ? 10056 elem.defaultView || elem.parentWindow : 10057 false; 10058} 10059 10060jQuery.offset = { 10061 setOffset: function( elem, options, i ) { 10062 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, 10063 position = jQuery.css( elem, "position" ), 10064 curElem = jQuery( elem ), 10065 props = {}; 10066 10067 // set position first, in-case top/left are set even on static elem 10068 if ( position === "static" ) { 10069 elem.style.position = "relative"; 10070 } 10071 10072 curOffset = curElem.offset(); 10073 curCSSTop = jQuery.css( elem, "top" ); 10074 curCSSLeft = jQuery.css( elem, "left" ); 10075 calculatePosition = ( position === "absolute" || position === "fixed" ) && 10076 jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1; 10077 10078 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed 10079 if ( calculatePosition ) { 10080 curPosition = curElem.position(); 10081 curTop = curPosition.top; 10082 curLeft = curPosition.left; 10083 } else { 10084 curTop = parseFloat( curCSSTop ) || 0; 10085 curLeft = parseFloat( curCSSLeft ) || 0; 10086 } 10087 10088 if ( jQuery.isFunction( options ) ) { 10089 options = options.call( elem, i, curOffset ); 10090 } 10091 10092 if ( options.top != null ) { 10093 props.top = ( options.top - curOffset.top ) + curTop; 10094 } 10095 if ( options.left != null ) { 10096 props.left = ( options.left - curOffset.left ) + curLeft; 10097 } 10098 10099 if ( "using" in options ) { 10100 options.using.call( elem, props ); 10101 } else { 10102 curElem.css( props ); 10103 } 10104 } 10105}; 10106 10107jQuery.fn.extend({ 10108 offset: function( options ) { 10109 if ( arguments.length ) { 10110 return options === undefined ? 10111 this : 10112 this.each(function( i ) { 10113 jQuery.offset.setOffset( this, options, i ); 10114 }); 10115 } 10116 10117 var docElem, win, 10118 box = { top: 0, left: 0 }, 10119 elem = this[ 0 ], 10120 doc = elem && elem.ownerDocument; 10121 10122 if ( !doc ) { 10123 return; 10124 } 10125 10126 docElem = doc.documentElement; 10127 10128 // Make sure it's not a disconnected DOM node 10129 if ( !jQuery.contains( docElem, elem ) ) { 10130 return box; 10131 } 10132 10133 // If we don't have gBCR, just use 0,0 rather than error 10134 // BlackBerry 5, iOS 3 (original iPhone) 10135 if ( typeof elem.getBoundingClientRect !== strundefined ) { 10136 box = elem.getBoundingClientRect(); 10137 } 10138 win = getWindow( doc ); 10139 return { 10140 top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ), 10141 left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 ) 10142 }; 10143 }, 10144 10145 position: function() { 10146 if ( !this[ 0 ] ) { 10147 return; 10148 } 10149 10150 var offsetParent, offset, 10151 parentOffset = { top: 0, left: 0 }, 10152 elem = this[ 0 ]; 10153 10154 // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent 10155 if ( jQuery.css( elem, "position" ) === "fixed" ) { 10156 // we assume that getBoundingClientRect is available when computed position is fixed 10157 offset = elem.getBoundingClientRect(); 10158 } else { 10159 // Get *real* offsetParent 10160 offsetParent = this.offsetParent(); 10161 10162 // Get correct offsets 10163 offset = this.offset(); 10164 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) { 10165 parentOffset = offsetParent.offset(); 10166 } 10167 10168 // Add offsetParent borders 10169 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ); 10170 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ); 10171 } 10172 10173 // Subtract parent offsets and element margins 10174 // note: when an element has margin: auto the offsetLeft and marginLeft 10175 // are the same in Safari causing offset.left to incorrectly be 0 10176 return { 10177 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), 10178 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true) 10179 }; 10180 }, 10181 10182 offsetParent: function() { 10183 return this.map(function() { 10184 var offsetParent = this.offsetParent || docElem; 10185 10186 while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) { 10187 offsetParent = offsetParent.offsetParent; 10188 } 10189 return offsetParent || docElem; 10190 }); 10191 } 10192}); 10193 10194// Create scrollLeft and scrollTop methods 10195jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) { 10196 var top = /Y/.test( prop ); 10197 10198 jQuery.fn[ method ] = function( val ) { 10199 return access( this, function( elem, method, val ) { 10200 var win = getWindow( elem ); 10201 10202 if ( val === undefined ) { 10203 return win ? (prop in win) ? win[ prop ] : 10204 win.document.documentElement[ method ] : 10205 elem[ method ]; 10206 } 10207 10208 if ( win ) { 10209 win.scrollTo( 10210 !top ? val : jQuery( win ).scrollLeft(), 10211 top ? val : jQuery( win ).scrollTop() 10212 ); 10213 10214 } else { 10215 elem[ method ] = val; 10216 } 10217 }, method, val, arguments.length, null ); 10218 }; 10219}); 10220 10221// Add the top/left cssHooks using jQuery.fn.position 10222// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 10223// getComputedStyle returns percent when specified for top/left/bottom/right 10224// rather than make the css module depend on the offset module, we just check for it here 10225jQuery.each( [ "top", "left" ], function( i, prop ) { 10226 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, 10227 function( elem, computed ) { 10228 if ( computed ) { 10229 computed = curCSS( elem, prop ); 10230 // if curCSS returns percentage, fallback to offset 10231 return rnumnonpx.test( computed ) ? 10232 jQuery( elem ).position()[ prop ] + "px" : 10233 computed; 10234 } 10235 } 10236 ); 10237}); 10238 10239 10240// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods 10241jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { 10242 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { 10243 // margin is only for outerHeight, outerWidth 10244 jQuery.fn[ funcName ] = function( margin, value ) { 10245 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), 10246 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); 10247 10248 return access( this, function( elem, type, value ) { 10249 var doc; 10250 10251 if ( jQuery.isWindow( elem ) ) { 10252 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there 10253 // isn't a whole lot we can do. See pull request at this URL for discussion: 10254 // https://github.com/jquery/jquery/pull/764 10255 return elem.document.documentElement[ "client" + name ]; 10256 } 10257 10258 // Get document width or height 10259 if ( elem.nodeType === 9 ) { 10260 doc = elem.documentElement; 10261 10262 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest 10263 // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it. 10264 return Math.max( 10265 elem.body[ "scroll" + name ], doc[ "scroll" + name ], 10266 elem.body[ "offset" + name ], doc[ "offset" + name ], 10267 doc[ "client" + name ] 10268 ); 10269 } 10270 10271 return value === undefined ? 10272 // Get width or height on the element, requesting but not forcing parseFloat 10273 jQuery.css( elem, type, extra ) : 10274 10275 // Set width or height on the element 10276 jQuery.style( elem, type, value, extra ); 10277 }, type, chainable ? margin : undefined, chainable, null ); 10278 }; 10279 }); 10280}); 10281 10282 10283// The number of elements contained in the matched element set 10284jQuery.fn.size = function() { 10285 return this.length; 10286}; 10287 10288jQuery.fn.andSelf = jQuery.fn.addBack; 10289 10290 10291 10292 10293// Register as a named AMD module, since jQuery can be concatenated with other 10294// files that may use define, but not via a proper concatenation script that 10295// understands anonymous AMD modules. A named AMD is safest and most robust 10296// way to register. Lowercase jquery is used because AMD module names are 10297// derived from file names, and jQuery is normally delivered in a lowercase 10298// file name. Do this after creating the global so that if an AMD module wants 10299// to call noConflict to hide this version of jQuery, it will work. 10300 10301// Note that for maximum portability, libraries that are not jQuery should 10302// declare themselves as anonymous modules, and avoid setting a global if an 10303// AMD loader is present. jQuery is a special case. For more information, see 10304// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon 10305 10306if ( typeof define === "function" && define.amd ) { 10307 define( "jquery", [], function() { 10308 return jQuery; 10309 }); 10310} 10311 10312 10313 10314 10315var 10316 // Map over jQuery in case of overwrite 10317 _jQuery = window.jQuery, 10318 10319 // Map over the $ in case of overwrite 10320 _$ = window.$; 10321 10322jQuery.noConflict = function( deep ) { 10323 if ( window.$ === jQuery ) { 10324 window.$ = _$; 10325 } 10326 10327 if ( deep && window.jQuery === jQuery ) { 10328 window.jQuery = _jQuery; 10329 } 10330 10331 return jQuery; 10332}; 10333 10334// Expose jQuery and $ identifiers, even in 10335// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557) 10336// and CommonJS for browser emulators (#13566) 10337if ( typeof noGlobal === strundefined ) { 10338 window.jQuery = window.$ = jQuery; 10339} 10340 10341 10342 10343 10344return jQuery; 10345 10346}));
10347 10348// Underscore.js 1.4.3 10349// http://underscorejs.org 10350// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. 10351// Underscore may be freely distributed under the MIT license. 10352 10353(function() { 10354 10355 // Baseline setup 10356 // -------------- 10357 10358 // Establish the root object, `window` in the browser, or `global` on the server. 10359 var root = this; 10360 10361 // Save the previous value of the `_` variable. 10362 var previousUnderscore = root._; 10363 10364 // Establish the object that gets returned to break out of a loop iteration. 10365 var breaker = {}; 10366 10367 // Save bytes in the minified (but not gzipped) version: 10368 var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; 10369 10370 // Create quick reference variables for speed access to core prototypes. 10371 var push = ArrayProto.push, 10372 slice = ArrayProto.slice, 10373 concat = ArrayProto.concat, 10374 toString = ObjProto.toString, 10375 hasOwnProperty = ObjProto.hasOwnProperty; 10376 10377 // All **ECMAScript 5** native function implementations that we hope to use 10378 // are declared here. 10379 var 10380 nativeForEach = ArrayProto.forEach, 10381 nativeMap = ArrayProto.map, 10382 nativeReduce = ArrayProto.reduce, 10383 nativeReduceRight = ArrayProto.reduceRight, 10384 nativeFilter = ArrayProto.filter, 10385 nativeEvery = ArrayProto.every, 10386 nativeSome = ArrayProto.some, 10387 nativeIndexOf = ArrayProto.indexOf, 10388 nativeLastIndexOf = ArrayProto.lastIndexOf, 10389 nativeIsArray = Array.isArray, 10390 nativeKeys = Object.keys, 10391 nativeBind = FuncProto.bind; 10392 10393 // Create a safe reference to the Underscore object for use below. 10394 var _ = function(obj) { 10395 if (obj instanceof _) return obj; 10396 if (!(this instanceof _)) return new _(obj); 10397 this._wrapped = obj; 10398 }; 10399 10400 // Export the Underscore object for **Node.js**, with 10401 // backwards-compatibility for the old `require()` API. If we're in 10402 // the browser, add `_` as a global object via a string identifier, 10403 // for Closure Compiler "advanced" mode. 10404 if (typeof exports !== 'undefined') { 10405 if (typeof module !== 'undefined' && module.exports) { 10406 exports = module.exports = _; 10407 } 10408 exports._ = _; 10409 } else { 10410 root._ = _; 10411 } 10412 10413 // Current version. 10414 _.VERSION = '1.4.3'; 10415 10416 // Collection Functions 10417 // -------------------- 10418 10419 // The cornerstone, an `each` implementation, aka `forEach`. 10420 // Handles objects with the built-in `forEach`, arrays, and raw objects. 10421 // Delegates to **ECMAScript 5**'s native `forEach` if available. 10422 var each = _.each = _.forEach = function(obj, iterator, context) { 10423 if (obj == null) return; 10424 if (nativeForEach && obj.forEach === nativeForEach) { 10425 obj.forEach(iterator, context); 10426 } else if (obj.length === +obj.length) { 10427 for (var i = 0, l = obj.length; i < l; i++) { 10428 if (iterator.call(context, obj[i], i, obj) === breaker) return; 10429 } 10430 } else { 10431 for (var key in obj) { 10432 if (_.has(obj, key)) { 10433 if (iterator.call(context, obj[key], key, obj) === breaker) return; 10434 } 10435 } 10436 } 10437 }; 10438 10439 // Return the results of applying the iterator to each element. 10440 // Delegates to **ECMAScript 5**'s native `map` if available. 10441 _.map = _.collect = function(obj, iterator, context) { 10442 var results = []; 10443 if (obj == null) return results; 10444 if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); 10445 each(obj, function(value, index, list) { 10446 results[results.length] = iterator.call(context, value, index, list); 10447 }); 10448 return results; 10449 }; 10450 10451 var reduceError = 'Reduce of empty array with no initial value'; 10452 10453 // **Reduce** builds up a single result from a list of values, aka `inject`, 10454 // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. 10455 _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { 10456 var initial = arguments.length > 2; 10457 if (obj == null) obj = []; 10458 if (nativeReduce && obj.reduce === nativeReduce) { 10459 if (context) iterator = _.bind(iterator, context); 10460 return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); 10461 } 10462 each(obj, function(value, index, list) { 10463 if (!initial) { 10464 memo = value; 10465 initial = true; 10466 } else { 10467 memo = iterator.call(context, memo, value, index, list); 10468 } 10469 }); 10470 if (!initial) throw new TypeError(reduceError); 10471 return memo; 10472 }; 10473 10474 // The right-associative version of reduce, also known as `foldr`. 10475 // Delegates to **ECMAScript 5**'s native `reduceRight` if available. 10476 _.reduceRight = _.foldr = function(obj, iterator, memo, context) { 10477 var initial = arguments.length > 2; 10478 if (obj == null) obj = []; 10479 if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { 10480 if (context) iterator = _.bind(iterator, context); 10481 return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); 10482 } 10483 var length = obj.length; 10484 if (length !== +length) { 10485 var keys = _.keys(obj); 10486 length = keys.length; 10487 } 10488 each(obj, function(value, index, list) { 10489 index = keys ? keys[--length] : --length; 10490 if (!initial) { 10491 memo = obj[index]; 10492 initial = true; 10493 } else { 10494 memo = iterator.call(context, memo, obj[index], index, list); 10495 } 10496 }); 10497 if (!initial) throw new TypeError(reduceError); 10498 return memo; 10499 }; 10500 10501 // Return the first value which passes a truth test. Aliased as `detect`. 10502 _.find = _.detect = function(obj, iterator, context) { 10503 var result; 10504 any(obj, function(value, index, list) { 10505 if (iterator.call(context, value, index, list)) { 10506 result = value; 10507 return true; 10508 } 10509 }); 10510 return result; 10511 }; 10512 10513 // Return all the elements that pass a truth test. 10514 // Delegates to **ECMAScript 5**'s native `filter` if available. 10515 // Aliased as `select`. 10516 _.filter = _.select = function(obj, iterator, context) { 10517 var results = []; 10518 if (obj == null) return results; 10519 if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); 10520 each(obj, function(value, index, list) { 10521 if (iterator.call(context, value, index, list)) results[results.length] = value; 10522 }); 10523 return results; 10524 }; 10525 10526 // Return all the elements for which a truth test fails. 10527 _.reject = function(obj, iterator, context) { 10528 return _.filter(obj, function(value, index, list) { 10529 return !iterator.call(context, value, index, list); 10530 }, context); 10531 }; 10532 10533 // Determine whether all of the elements match a truth test. 10534 // Delegates to **ECMAScript 5**'s native `every` if available. 10535 // Aliased as `all`. 10536 _.every = _.all = function(obj, iterator, context) { 10537 iterator || (iterator = _.identity); 10538 var result = true; 10539 if (obj == null) return result; 10540 if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); 10541 each(obj, function(value, index, list) { 10542 if (!(result = result && iterator.call(context, value, index, list))) return breaker; 10543 }); 10544 return !!result; 10545 }; 10546 10547 // Determine if at least one element in the object matches a truth test. 10548 // Delegates to **ECMAScript 5**'s native `some` if available. 10549 // Aliased as `any`. 10550 var any = _.some = _.any = function(obj, iterator, context) { 10551 iterator || (iterator = _.identity); 10552 var result = false;
10553 if (obj == null) return result; 10554 if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); 10555 each(obj, function(value, index, list) { 10556 if (result || (result = iterator.call(context, value, index, list))) return breaker; 10557 }); 10558 return !!result; 10559 }; 10560 10561 // Determine if the array or object contains a given value (using `===`). 10562 // Aliased as `include`. 10563 _.contains = _.include = function(obj, target) { 10564 if (obj == null) return false; 10565 if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; 10566 return any(obj, function(value) { 10567 return value === target; 10568 }); 10569 }; 10570 10571 // Invoke a method (with arguments) on every item in a collection. 10572 _.invoke = function(obj, method) { 10573 var args = slice.call(arguments, 2); 10574 return _.map(obj, function(value) { 10575 return (_.isFunction(method) ? method : value[method]).apply(value, args); 10576 }); 10577 }; 10578 10579 // Convenience version of a common use case of `map`: fetching a property. 10580 _.pluck = function(obj, key) { 10581 return _.map(obj, function(value){ return value[key]; }); 10582 }; 10583 10584 // Convenience version of a common use case of `filter`: selecting only objects 10585 // with specific `key:value` pairs. 10586 _.where = function(obj, attrs) { 10587 if (_.isEmpty(attrs)) return []; 10588 return _.filter(obj, function(value) { 10589 for (var key in attrs) { 10590 if (attrs[key] !== value[key]) return false; 10591 } 10592 return true; 10593 }); 10594 }; 10595 10596 // Return the maximum element or (element-based computation). 10597 // Can't optimize arrays of integers longer than 65,535 elements. 10598 // See: https://bugs.webkit.org/show_bug.cgi?id=80797 10599 _.max = function(obj, iterator, context) { 10600 if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { 10601 return Math.max.apply(Math, obj); 10602 } 10603 if (!iterator && _.isEmpty(obj)) return -Infinity; 10604 var result = {computed : -Infinity, value: -Infinity}; 10605 each(obj, function(value, index, list) { 10606 var computed = iterator ? iterator.call(context, value, index, list) : value; 10607 computed >= result.computed && (result = {value : value, computed : computed}); 10608 }); 10609 return result.value; 10610 }; 10611 10612 // Return the minimum element (or element-based computation). 10613 _.min = function(obj, iterator, context) { 10614 if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { 10615 return Math.min.apply(Math, obj); 10616 } 10617 if (!iterator && _.isEmpty(obj)) return Infinity; 10618 var result = {computed : Infinity, value: Infinity}; 10619 each(obj, function(value, index, list) { 10620 var computed = iterator ? iterator.call(context, value, index, list) : value; 10621 computed < result.computed && (result = {value : value, computed : computed}); 10622 }); 10623 return result.value; 10624 }; 10625 10626 // Shuffle an array. 10627 _.shuffle = function(obj) { 10628 var rand; 10629 var index = 0; 10630 var shuffled = []; 10631 each(obj, function(value) { 10632 rand = _.random(index++); 10633 shuffled[index - 1] = shuffled[rand]; 10634 shuffled[rand] = value; 10635 }); 10636 return shuffled; 10637 }; 10638 10639 // An internal function to generate lookup iterators. 10640 var lookupIterator = function(value) { 10641 return _.isFunction(value) ? value : function(obj){ return obj[value]; }; 10642 }; 10643 10644 // Sort the object's values by a criterion produced by an iterator. 10645 _.sortBy = function(obj, value, context) { 10646 var iterator = lookupIterator(value); 10647 return _.pluck(_.map(obj, function(value, index, list) { 10648 return { 10649 value : value, 10650 index : index, 10651 criteria : iterator.call(context, value, index, list) 10652 }; 10653 }).sort(function(left, right) { 10654 var a = left.criteria; 10655 var b = right.criteria; 10656 if (a !== b) { 10657 if (a > b || a === void 0) return 1; 10658 if (a < b || b === void 0) return -1; 10659 } 10660 return left.index < right.index ? -1 : 1; 10661 }), 'value'); 10662 }; 10663 10664 // An internal function used for aggregate "group by" operations. 10665 var group = function(obj, value, context, behavior) { 10666 var result = {}; 10667 var iterator = lookupIterator(value || _.identity); 10668 each(obj, function(value, index) { 10669 var key = iterator.call(context, value, index, obj); 10670 behavior(result, key, value); 10671 }); 10672 return result; 10673 }; 10674 10675 // Groups the object's values by a criterion. Pass either a string attribute 10676 // to group by, or a function that returns the criterion. 10677 _.groupBy = function(obj, value, context) { 10678 return group(obj, value, context, function(result, key, value) { 10679 (_.has(result, key) ? result[key] : (result[key] = [])).push(value); 10680 }); 10681 }; 10682 10683 // Counts instances of an object that group by a certain criterion. Pass 10684 // either a string attribute to count by, or a function that returns the 10685 // criterion. 10686 _.countBy = function(obj, value, context) { 10687 return group(obj, value, context, function(result, key) { 10688 if (!_.has(result, key)) result[key] = 0; 10689 result[key]++; 10690 }); 10691 }; 10692 10693 // Use a comparator function to figure out the smallest index at which 10694 // an object should be inserted so as to maintain order. Uses binary search. 10695 _.sortedIndex = function(array, obj, iterator, context) { 10696 iterator = iterator == null ? _.identity : lookupIterator(iterator); 10697 var value = iterator.call(context, obj); 10698 var low = 0, high = array.length; 10699 while (low < high) { 10700 var mid = (low + high) >>> 1; 10701 iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; 10702 } 10703 return low; 10704 }; 10705 10706 // Safely convert anything iterable into a real, live array. 10707 _.toArray = function(obj) { 10708 if (!obj) return []; 10709 if (_.isArray(obj)) return slice.call(obj); 10710 if (obj.length === +obj.length) return _.map(obj, _.identity); 10711 return _.values(obj); 10712 }; 10713 10714 // Return the number of elements in an object. 10715 _.size = function(obj) { 10716 if (obj == null) return 0; 10717 return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; 10718 }; 10719 10720 // Array Functions 10721 // --------------- 10722 10723 // Get the first element of an array. Passing **n** will return the first N 10724 // values in the array. Aliased as `head` and `take`. The **guard** check 10725 // allows it to work with `_.map`. 10726 _.first = _.head = _.take = function(array, n, guard) { 10727 if (array == null) return void 0; 10728 return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; 10729 }; 10730 10731 // Returns everything but the last entry of the array. Especially useful on 10732 // the arguments object. Passing **n** will return all the values in 10733 // the array, excluding the last N. The **guard** check allows it to work with 10734 // `_.map`. 10735 _.initial = function(array, n, guard) { 10736 return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); 10737 }; 10738 10739 // Get the last element of an array. Passing **n** will return the last N 10740 // values in the array. The **guard** check allows it to work with `_.map`. 10741 _.last = function(array, n, guard) { 10742 if (array == null) return void 0; 10743 if ((n != null) && !guard) { 10744 return slice.call(array, Math.max(array.length - n, 0)); 10745 } else { 10746 return array[array.length - 1]; 10747 } 10748 }; 10749 10750 // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. 10751 // Especially useful on the arguments object. Passing an **n** will return 10752 // the rest N values in the array. The **guard** 10753 // check allows it to work with `_.map`. 10754 _.rest = _.tail = _.drop = function(array, n, guard) { 10755 return slice.call(array, (n == null) || guard ? 1 : n); 10756 }; 10757 10758 // Trim out all falsy values from an array.
10759 _.compact = function(array) { 10760 return _.filter(array, _.identity); 10761 }; 10762 10763 // Internal implementation of a recursive `flatten` function. 10764 var flatten = function(input, shallow, output) { 10765 each(input, function(value) { 10766 if (_.isArray(value)) { 10767 shallow ? push.apply(output, value) : flatten(value, shallow, output); 10768 } else { 10769 output.push(value); 10770 } 10771 }); 10772 return output; 10773 }; 10774 10775 // Return a completely flattened version of an array. 10776 _.flatten = function(array, shallow) { 10777 return flatten(array, shallow, []); 10778 }; 10779 10780 // Return a version of the array that does not contain the specified value(s). 10781 _.without = function(array) { 10782 return _.difference(array, slice.call(arguments, 1)); 10783 }; 10784 10785 // Produce a duplicate-free version of the array. If the array has already 10786 // been sorted, you have the option of using a faster algorithm. 10787 // Aliased as `unique`. 10788 _.uniq = _.unique = function(array, isSorted, iterator, context) { 10789 if (_.isFunction(isSorted)) { 10790 context = iterator; 10791 iterator = isSorted; 10792 isSorted = false; 10793 } 10794 var initial = iterator ? _.map(array, iterator, context) : array; 10795 var results = []; 10796 var seen = []; 10797 each(initial, function(value, index) { 10798 if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { 10799 seen.push(value); 10800 results.push(array[index]); 10801 } 10802 }); 10803 return results; 10804 }; 10805 10806 // Produce an array that contains the union: each distinct element from all of 10807 // the passed-in arrays. 10808 _.union = function() { 10809 return _.uniq(concat.apply(ArrayProto, arguments)); 10810 }; 10811 10812 // Produce an array that contains every item shared between all the 10813 // passed-in arrays. 10814 _.intersection = function(array) { 10815 var rest = slice.call(arguments, 1); 10816 return _.filter(_.uniq(array), function(item) { 10817 return _.every(rest, function(other) { 10818 return _.indexOf(other, item) >= 0; 10819 }); 10820 }); 10821 }; 10822 10823 // Take the difference between one array and a number of other arrays. 10824 // Only the elements present in just the first array will remain. 10825 _.difference = function(array) { 10826 var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); 10827 return _.filter(array, function(value){ return !_.contains(rest, value); }); 10828 }; 10829 10830 // Zip together multiple lists into a single array -- elements that share 10831 // an index go together. 10832 _.zip = function() { 10833 var args = slice.call(arguments); 10834 var length = _.max(_.pluck(args, 'length')); 10835 var results = new Array(length); 10836 for (var i = 0; i < length; i++) { 10837 results[i] = _.pluck(args, "" + i); 10838 } 10839 return results; 10840 }; 10841 10842 // Converts lists into objects. Pass either a single array of `[key, value]` 10843 // pairs, or two parallel arrays of the same length -- one of keys, and one of 10844 // the corresponding values. 10845 _.object = function(list, values) { 10846 if (list == null) return {}; 10847 var result = {}; 10848 for (var i = 0, l = list.length; i < l; i++) { 10849 if (values) { 10850 result[list[i]] = values[i]; 10851 } else { 10852 result[list[i][0]] = list[i][1]; 10853 } 10854 } 10855 return result; 10856 }; 10857 10858 // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), 10859 // we need this function. Return the position of the first occurrence of an 10860 // item in an array, or -1 if the item is not included in the array. 10861 // Delegates to **ECMAScript 5**'s native `indexOf` if available. 10862 // If the array is large and already in sort order, pass `true` 10863 // for **isSorted** to use binary search. 10864 _.indexOf = function(array, item, isSorted) { 10865 if (array == null) return -1; 10866 var i = 0, l = array.length; 10867 if (isSorted) { 10868 if (typeof isSorted == 'number') { 10869 i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted); 10870 } else { 10871 i = _.sortedIndex(array, item); 10872 return array[i] === item ? i : -1; 10873 } 10874 } 10875 if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); 10876 for (; i < l; i++) if (array[i] === item) return i; 10877 return -1; 10878 }; 10879 10880 // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. 10881 _.lastIndexOf = function(array, item, from) { 10882 if (array == null) return -1; 10883 var hasIndex = from != null; 10884 if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { 10885 return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); 10886 } 10887 var i = (hasIndex ? from : array.length); 10888 while (i--) if (array[i] === item) return i; 10889 return -1; 10890 }; 10891 10892 // Generate an integer Array containing an arithmetic progression. A port of 10893 // the native Python `range()` function. See 10894 // [the Python documentation](http://docs.python.org/library/functions.html#range). 10895 _.range = function(start, stop, step) { 10896 if (arguments.length <= 1) { 10897 stop = start || 0; 10898 start = 0; 10899 } 10900 step = arguments[2] || 1; 10901 10902 var len = Math.max(Math.ceil((stop - start) / step), 0); 10903 var idx = 0; 10904 var range = new Array(len); 10905 10906 while(idx < len) { 10907 range[idx++] = start; 10908 start += step; 10909 } 10910 10911 return range; 10912 }; 10913 10914 // Function (ahem) Functions 10915 // ------------------ 10916 10917 // Reusable constructor function for prototype setting. 10918 var ctor = function(){}; 10919 10920 // Create a function bound to a given object (assigning `this`, and arguments, 10921 // optionally). Binding with arguments is also known as `curry`. 10922 // Delegates to **ECMAScript 5**'s native `Function.bind` if available. 10923 // We check for `func.bind` first, to fail fast when `func` is undefined. 10924 _.bind = function(func, context) { 10925 var args, bound; 10926 if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); 10927 if (!_.isFunction(func)) throw new TypeError; 10928 args = slice.call(arguments, 2); 10929 return bound = function() { 10930 if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); 10931 ctor.prototype = func.prototype; 10932 var self = new ctor; 10933 ctor.prototype = null; 10934 var result = func.apply(self, args.concat(slice.call(arguments))); 10935 if (Object(result) === result) return result; 10936 return self; 10937 }; 10938 }; 10939 10940 // Bind all of an object's methods to that object. Useful for ensuring that 10941 // all callbacks defined on an object belong to it. 10942 _.bindAll = function(obj) { 10943 var funcs = slice.call(arguments, 1);
10944 if (funcs.length == 0) funcs = _.functions(obj); 10945 each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); 10946 return obj; 10947 }; 10948 10949 // Memoize an expensive function by storing its results. 10950 _.memoize = function(func, hasher) { 10951 var memo = {}; 10952 hasher || (hasher = _.identity); 10953 return function() { 10954 var key = hasher.apply(this, arguments); 10955 return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); 10956 }; 10957 }; 10958 10959 // Delays a function for the given number of milliseconds, and then calls 10960 // it with the arguments supplied. 10961 _.delay = function(func, wait) { 10962 var args = slice.call(arguments, 2); 10963 return setTimeout(function(){ return func.apply(null, args); }, wait); 10964 }; 10965 10966 // Defers a function, scheduling it to run after the current call stack has 10967 // cleared. 10968 _.defer = function(func) { 10969 return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); 10970 }; 10971 10972 // Returns a function, that, when invoked, will only be triggered at most once 10973 // during a given window of time. 10974 _.throttle = function(func, wait) { 10975 var context, args, timeout, result; 10976 var previous = 0; 10977 var later = function() { 10978 previous = new Date; 10979 timeout = null; 10980 result = func.apply(context, args); 10981 }; 10982 return function() { 10983 var now = new Date; 10984 var remaining = wait - (now - previous); 10985 context = this; 10986 args = arguments; 10987 if (remaining <= 0) { 10988 clearTimeout(timeout); 10989 timeout = null; 10990 previous = now; 10991 result = func.apply(context, args); 10992 } else if (!timeout) { 10993 timeout = setTimeout(later, remaining); 10994 } 10995 return result; 10996 }; 10997 }; 10998 10999 // Returns a function, that, as long as it continues to be invoked, will not 11000 // be triggered. The function will be called after it stops being called for 11001 // N milliseconds. If `immediate` is passed, trigger the function on the 11002 // leading edge, instead of the trailing. 11003 _.debounce = function(func, wait, immediate) { 11004 var timeout, result; 11005 return function() { 11006 var context = this, args = arguments; 11007 var later = function() { 11008 timeout = null; 11009 if (!immediate) result = func.apply(context, args); 11010 }; 11011 var callNow = immediate && !timeout; 11012 clearTimeout(timeout); 11013 timeout = setTimeout(later, wait); 11014 if (callNow) result = func.apply(context, args); 11015 return result; 11016 }; 11017 }; 11018 11019 // Returns a function that will be executed at most one time, no matter how 11020 // often you call it. Useful for lazy initialization. 11021 _.once = function(func) { 11022 var ran = false, memo; 11023 return function() { 11024 if (ran) return memo; 11025 ran = true; 11026 memo = func.apply(this, arguments); 11027 func = null; 11028 return memo; 11029 }; 11030 }; 11031 11032 // Returns the first function passed as an argument to the second, 11033 // allowing you to adjust arguments, run code before and after, and 11034 // conditionally execute the original function. 11035 _.wrap = function(func, wrapper) { 11036 return function() { 11037 var args = [func]; 11038 push.apply(args, arguments); 11039 return wrapper.apply(this, args); 11040 }; 11041 }; 11042 11043 // Returns a function that is the composition of a list of functions, each 11044 // consuming the return value of the function that follows. 11045 _.compose = function() { 11046 var funcs = arguments; 11047 return function() { 11048 var args = arguments; 11049 for (var i = funcs.length - 1; i >= 0; i--) { 11050 args = [funcs[i].apply(this, args)]; 11051 } 11052 return args[0]; 11053 }; 11054 }; 11055 11056 // Returns a function that will only be executed after being called N times. 11057 _.after = function(times, func) { 11058 if (times <= 0) return func(); 11059 return function() { 11060 if (--times < 1) { 11061 return func.apply(this, arguments); 11062 } 11063 }; 11064 }; 11065 11066 // Object Functions 11067 // ---------------- 11068 11069 // Retrieve the names of an object's properties. 11070 // Delegates to **ECMAScript 5**'s native `Object.keys` 11071 _.keys = nativeKeys || function(obj) { 11072 if (obj !== Object(obj)) throw new TypeError('Invalid object'); 11073 var keys = []; 11074 for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; 11075 return keys; 11076 }; 11077 11078 // Retrieve the values of an object's properties. 11079 _.values = function(obj) { 11080 var values = []; 11081 for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); 11082 return values; 11083 }; 11084 11085 // Convert an object into a list of `[key, value]` pairs. 11086 _.pairs = function(obj) { 11087 var pairs = []; 11088 for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]); 11089 return pairs; 11090 }; 11091 11092 // Invert the keys and values of an object. The values must be serializable. 11093 _.invert = function(obj) { 11094 var result = {}; 11095 for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; 11096 return result; 11097 }; 11098 11099 // Return a sorted list of the function names available on the object. 11100 // Aliased as `methods` 11101 _.functions = _.methods = function(obj) { 11102 var names = []; 11103 for (var key in obj) { 11104 if (_.isFunction(obj[key])) names.push(key); 11105 } 11106 return names.sort(); 11107 }; 11108 11109 // Extend a given object with all the properties in passed-in object(s). 11110 _.extend = function(obj) { 11111 each(slice.call(arguments, 1), function(source) { 11112 if (source) { 11113 for (var prop in source) { 11114 obj[prop] = source[prop]; 11115 } 11116 } 11117 }); 11118 return obj; 11119 }; 11120 11121 // Return a copy of the object only containing the whitelisted properties. 11122 _.pick = function(obj) { 11123 var copy = {}; 11124 var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); 11125 each(keys, function(key) { 11126 if (key in obj) copy[key] = obj[key]; 11127 }); 11128 return copy; 11129 }; 11130
11131 // Return a copy of the object without the blacklisted properties. 11132 _.omit = function(obj) { 11133 var copy = {}; 11134 var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); 11135 for (var key in obj) { 11136 if (!_.contains(keys, key)) copy[key] = obj[key]; 11137 } 11138 return copy; 11139 }; 11140 11141 // Fill in a given object with default properties. 11142 _.defaults = function(obj) { 11143 each(slice.call(arguments, 1), function(source) { 11144 if (source) { 11145 for (var prop in source) { 11146 if (obj[prop] == null) obj[prop] = source[prop]; 11147 } 11148 } 11149 }); 11150 return obj; 11151 }; 11152 11153 // Create a (shallow-cloned) duplicate of an object. 11154 _.clone = function(obj) { 11155 if (!_.isObject(obj)) return obj; 11156 return _.isArray(obj) ? obj.slice() : _.extend({}, obj); 11157 }; 11158 11159 // Invokes interceptor with the obj, and then returns obj. 11160 // The primary purpose of this method is to "tap into" a method chain, in 11161 // order to perform operations on intermediate results within the chain. 11162 _.tap = function(obj, interceptor) { 11163 interceptor(obj); 11164 return obj; 11165 }; 11166 11167 // Internal recursive comparison function for `isEqual`. 11168 var eq = function(a, b, aStack, bStack) { 11169 // Identical objects are equal. `0 === -0`, but they aren't identical. 11170 // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. 11171 if (a === b) return a !== 0 || 1 / a == 1 / b; 11172 // A strict comparison is necessary because `null == undefined`. 11173 if (a == null || b == null) return a === b; 11174 // Unwrap any wrapped objects. 11175 if (a instanceof _) a = a._wrapped; 11176 if (b instanceof _) b = b._wrapped; 11177 // Compare `[[Class]]` names. 11178 var className = toString.call(a); 11179 if (className != toString.call(b)) return false; 11180 switch (className) { 11181 // Strings, numbers, dates, and booleans are compared by value. 11182 case '[object String]': 11183 // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is 11184 // equivalent to `new String("5")`. 11185 return a == String(b); 11186 case '[object Number]': 11187 // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for 11188 // other numeric values. 11189 return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); 11190 case '[object Date]': 11191 case '[object Boolean]': 11192 // Coerce dates and booleans to numeric primitive values. Dates are compared by their 11193 // millisecond representations. Note that invalid dates with millisecond representations 11194 // of `NaN` are not equivalent. 11195 return +a == +b; 11196 // RegExps are compared by their source patterns and flags. 11197 case '[object RegExp]': 11198 return a.source == b.source && 11199 a.global == b.global && 11200 a.multiline == b.multiline && 11201 a.ignoreCase == b.ignoreCase; 11202 } 11203 if (typeof a != 'object' || typeof b != 'object') return false; 11204 // Assume equality for cyclic structures. The algorithm for detecting cyclic 11205 // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. 11206 var length = aStack.length; 11207 while (length--) { 11208 // Linear search. Performance is inversely proportional to the number of 11209 // unique nested structures. 11210 if (aStack[length] == a) return bStack[length] == b; 11211 } 11212 // Add the first object to the stack of traversed objects. 11213 aStack.push(a); 11214 bStack.push(b); 11215 var size = 0, result = true; 11216 // Recursively compare objects and arrays. 11217 if (className == '[object Array]') { 11218 // Compare array lengths to determine if a deep comparison is necessary. 11219 size = a.length; 11220 result = size == b.length; 11221 if (result) { 11222 // Deep compare the contents, ignoring non-numeric properties. 11223 while (size--) { 11224 if (!(result = eq(a[size], b[size], aStack, bStack))) break; 11225 } 11226 } 11227 } else { 11228 // Objects with different constructors are not equivalent, but `Object`s 11229 // from different frames are. 11230 var aCtor = a.constructor, bCtor = b.constructor; 11231 if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && 11232 _.isFunction(bCtor) && (bCtor instanceof bCtor))) { 11233 return false;
11234 } 11235 // Deep compare objects. 11236 for (var key in a) { 11237 if (_.has(a, key)) { 11238 // Count the expected number of properties. 11239 size++; 11240 // Deep compare each member. 11241 if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; 11242 } 11243 } 11244 // Ensure that both objects contain the same number of properties. 11245 if (result) { 11246 for (key in b) { 11247 if (_.has(b, key) && !(size--)) break; 11248 } 11249 result = !size; 11250 } 11251 } 11252 // Remove the first object from the stack of traversed objects. 11253 aStack.pop(); 11254 bStack.pop(); 11255 return result; 11256 }; 11257 11258 // Perform a deep comparison to check if two objects are equal. 11259 _.isEqual = function(a, b) { 11260 return eq(a, b, [], []); 11261 }; 11262 11263 // Is a given array, string, or object empty? 11264 // An "empty" object has no enumerable own-properties. 11265 _.isEmpty = function(obj) { 11266 if (obj == null) return true; 11267 if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; 11268 for (var key in obj) if (_.has(obj, key)) return false; 11269 return true; 11270 }; 11271 11272 // Is a given value a DOM element? 11273 _.isElement = function(obj) { 11274 return !!(obj && obj.nodeType === 1); 11275 }; 11276 11277 // Is a given value an array? 11278 // Delegates to ECMA5's native Array.isArray 11279 _.isArray = nativeIsArray || function(obj) { 11280 return toString.call(obj) == '[object Array]'; 11281 }; 11282 11283 // Is a given variable an object? 11284 _.isObject = function(obj) { 11285 return obj === Object(obj); 11286 }; 11287 11288 // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. 11289 each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { 11290 _['is' + name] = function(obj) { 11291 return toString.call(obj) == '[object ' + name + ']'; 11292 }; 11293 }); 11294 11295 // Define a fallback version of the method in browsers (ahem, IE), where 11296 // there isn't any inspectable "Arguments" type. 11297 if (!_.isArguments(arguments)) { 11298 _.isArguments = function(obj) { 11299 return !!(obj && _.has(obj, 'callee')); 11300 }; 11301 } 11302 11303 // Optimize `isFunction` if appropriate. 11304 if (typeof (/./) !== 'function') { 11305 _.isFunction = function(obj) { 11306 return typeof obj === 'function'; 11307 }; 11308 } 11309 11310 // Is a given object a finite number? 11311 _.isFinite = function(obj) { 11312 return isFinite(obj) && !isNaN(parseFloat(obj)); 11313 }; 11314 11315 // Is the given value `NaN`? (NaN is the only number which does not equal itself). 11316 _.isNaN = function(obj) { 11317 return _.isNumber(obj) && obj != +obj; 11318 }; 11319 11320 // Is a given value a boolean? 11321 _.isBoolean = function(obj) { 11322 return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; 11323 }; 11324 11325 // Is a given value equal to null? 11326 _.isNull = function(obj) { 11327 return obj === null; 11328 }; 11329 11330 // Is a given variable undefined? 11331 _.isUndefined = function(obj) { 11332 return obj === void 0; 11333 }; 11334 11335 // Shortcut function for checking if an object has a given property directly 11336 // on itself (in other words, not on a prototype). 11337 _.has = function(obj, key) { 11338 return hasOwnProperty.call(obj, key); 11339 }; 11340 11341 // Utility Functions 11342 // ----------------- 11343 11344 // Run Underscore.js in *noConflict* mode, returning the `_` variable to its 11345 // previous owner. Returns a reference to the Underscore object. 11346 _.noConflict = function() { 11347 root._ = previousUnderscore; 11348 return this; 11349 }; 11350 11351 // Keep the identity function around for default iterators. 11352 _.identity = function(value) { 11353 return value; 11354 }; 11355 11356 // Run a function **n** times. 11357 _.times = function(n, iterator, context) { 11358 var accum = Array(n); 11359 for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); 11360 return accum; 11361 }; 11362 11363 // Return a random integer between min and max (inclusive). 11364 _.random = function(min, max) { 11365 if (max == null) { 11366 max = min; 11367 min = 0; 11368 } 11369 return min + (0 | Math.random() * (max - min + 1)); 11370 }; 11371 11372 // List of HTML entities for escaping. 11373 var entityMap = { 11374 escape: { 11375 '&': '&', 11376 '<': '<', 11377 '>': '>', 11378 '"': '"', 11379 "'": ''', 11380 '/': '/' 11381 } 11382 }; 11383 entityMap.unescape = _.invert(entityMap.escape); 11384 11385 // Regexes containing the keys and values listed immediately above. 11386 var entityRegexes = { 11387 escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), 11388 unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') 11389 }; 11390 11391 // Functions for escaping and unescaping strings to/from HTML interpolation. 11392 _.each(['escape', 'unescape'], function(method) { 11393 _[method] = function(string) { 11394 if (string == null) return ''; 11395 return ('' + string).replace(entityRegexes[method], function(match) { 11396 return entityMap[method][match]; 11397 }); 11398 }; 11399 }); 11400 11401 // If the value of the named property is a function then invoke it; 11402 // otherwise, return it. 11403 _.result = function(object, property) { 11404 if (object == null) return null; 11405 var value = object[property]; 11406 return _.isFunction(value) ? value.call(object) : value; 11407 }; 11408 11409 // Add your own custom functions to the Underscore object. 11410 _.mixin = function(obj) { 11411 each(_.functions(obj), function(name){ 11412 var func = _[name] = obj[name]; 11413 _.prototype[name] = function() { 11414 var args = [this._wrapped]; 11415 push.apply(args, arguments); 11416 return result.call(this, func.apply(_, args)); 11417 }; 11418 }); 11419 }; 11420 11421 // Generate a unique integer id (unique within the entire client session). 11422 // Useful for temporary DOM ids. 11423 var idCounter = 0; 11424 _.uniqueId = function(prefix) { 11425 var id = '' + ++idCounter; 11426 return prefix ? prefix + id : id; 11427 }; 11428 11429 // By default, Underscore uses ERB-style template delimiters, change the 11430 // following template settings to use alternative delimiters. 11431 _.templateSettings = { 11432 evaluate : /<%([\s\S]+?)%>/g, 11433 interpolate : /<%=([\s\S]+?)%>/g, 11434 escape : /<%-([\s\S]+?)%>/g 11435 }; 11436 11437 // When customizing `templateSettings`, if you don't want to define an 11438 // interpolation, evaluation or escaping regex, we need one that is 11439 // guaranteed not to match. 11440 var noMatch = /(.)^/; 11441 11442 // Certain characters need to be escaped so that they can be put into a 11443 // string literal. 11444 var escapes = { 11445 "'": "'", 11446 '\\': '\\', 11447 '\r': 'r', 11448 '\n': 'n', 11449 '\t': 't', 11450 '\u2028': 'u2028', 11451 '\u2029': 'u2029' 11452 }; 11453 11454 var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; 11455 11456 // JavaScript micro-templating, similar to John Resig's implementation. 11457 // Underscore templating handles arbitrary delimiters, preserves whitespace, 11458 // and correctly escapes quotes within interpolated code. 11459 _.template = function(text, data, settings) { 11460 settings = _.defaults({}, settings, _.templateSettings); 11461 11462 // Combine delimiters into one regular expression via alternation. 11463 var matcher = new RegExp([
11464 (settings.escape || noMatch).source, 11465 (settings.interpolate || noMatch).source, 11466 (settings.evaluate || noMatch).source 11467 ].join('|') + '|$', 'g'); 11468 11469 // Compile the template source, escaping string literals appropriately. 11470 var index = 0; 11471 var source = "__p+='"; 11472 text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { 11473 source += text.slice(index, offset) 11474 .replace(escaper, function(match) { return '\\' + escapes[match]; }); 11475 11476 if (escape) { 11477 source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; 11478 } 11479 if (interpolate) { 11480 source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; 11481 } 11482 if (evaluate) { 11483 source += "';\n" + evaluate + "\n__p+='"; 11484 } 11485 index = offset + match.length; 11486 return match; 11487 }); 11488 source += "';\n"; 11489 11490 // If a variable is not specified, place data values in local scope. 11491 if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; 11492 11493 source = "var __t,__p='',__j=Array.prototype.join," + 11494 "print=function(){__p+=__j.call(arguments,'');};\n" + 11495 source + "return __p;\n"; 11496 11497 try { 11498 var render = new Function(settings.variable || 'obj', '_', source); 11499 } catch (e) { 11500 e.source = source; 11501 throw e; 11502 } 11503 11504 if (data) return render(data, _); 11505 var template = function(data) { 11506 return render.call(this, data, _); 11507 }; 11508 11509 // Provide the compiled function source as a convenience for precompilation. 11510 template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; 11511 11512 return template; 11513 }; 11514 11515 // Add a "chain" function, which will delegate to the wrapper. 11516 _.chain = function(obj) { 11517 return _(obj).chain(); 11518 }; 11519 11520 // OOP 11521 // --------------- 11522 // If Underscore is called as a function, it returns a wrapped object that 11523 // can be used OO-style. This wrapper holds altered versions of all the 11524 // underscore functions. Wrapped objects may be chained. 11525 11526 // Helper function to continue chaining intermediate results. 11527 var result = function(obj) { 11528 return this._chain ? _(obj).chain() : obj; 11529 }; 11530 11531 // Add all of the Underscore functions to the wrapper object. 11532 _.mixin(_); 11533 11534 // Add all mutator Array functions to the wrapper. 11535 each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { 11536 var method = ArrayProto[name]; 11537 _.prototype[name] = function() { 11538 var obj = this._wrapped; 11539 method.apply(obj, arguments); 11540 if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; 11541 return result.call(this, obj); 11542 }; 11543 }); 11544 11545 // Add all accessor Array functions to the wrapper. 11546 each(['concat', 'join', 'slice'], function(name) { 11547 var method = ArrayProto[name]; 11548 _.prototype[name] = function() { 11549 return result.call(this, method.apply(this._wrapped, arguments)); 11550 }; 11551 }); 11552 11553 _.extend(_.prototype, { 11554 11555 // Start chaining a wrapped Underscore object. 11556 chain: function() { 11557 this._chain = true; 11558 return this; 11559 }, 11560 11561 // Extracts the result from a wrapped and chained object. 11562 value: function() { 11563 return this._wrapped; 11564 } 11565 11566 }); 11567 11568}).call(this); 11569window.HFBooking = {}; 11570 11571Date.prototype.addHours= function(h){ 11572 this.setHours(this.getHours()+h); 11573 return this; 11574}, 11575 11576HFBooking.Process = { 11577 payload: { 11578 branchId: false, 11579 channel: '', 11580 addressData: {}, 11581 email: '', 11582 postcode_param: '', 11583 chosenTime: false, 11584 chosenDate: false, 11585 }, 11586 currentStep: 1, 11587 addresses: [], 11588 calendarData: { 11589 currentMonth: new Date().getMonth(), 11590 }, 11591 selectedWeek: false, 11592 selectedTimeslot: { 11593 day: false, 11594 hours: false, 11595 minutes: false, 11596 }, 11597 wcDate: false, 11598 11599 renderStep: function(step) { 11600 this['step' + step].render() 11601 }, 11602 11603 updatePayload: function(key, value) { 11604 this.payload[this.camelize(key)] = value; 11605 }, 11606 11607 updateAddress: function(key, value) { 11608 this.payload.addressData[this.pascalize(key)] = value; 11609 }, 11610 11611 camelize: function(input) { 11612 return input.toLowerCase().replace(/-(.)/g, function(match, group1) { 11613 return group1.toUpperCase(); 11614 }); 11615 }, 11616 11617 pascalize: function(input) { 11618 var camelizedString = this.camelize(input); 11619 return camelizedString.charAt(0).toUpperCase() + camelizedString.slice(1); 11620 }, 11621 11622 justContactMe: function() { 11623 $('.hfview__timeslot').removeClass('selected'); 11624 $('.hfval__timeslot').removeClass('selected'); 11625 this.payload.justContactMe = true; 11626 this.payload.chosenDate = false;
11627 this.payload.chosenTime = false; 11628 this.selectedTimeslot.day = false; 11629 this.selectedTimeslot.hours = false; 11630 this.selectedTimeslot.minutes = false; 11631 this.nextStep(); 11632 }, 11633 11634 deselectChosenDate: function() { 11635 $('.hfview__timeslot').removeClass('selected'); 11636 $('.hfval__timeslot').removeClass('selected'); 11637 this.payload.chosenDate = false; 11638 this.payload.chosenTime = false; 11639 this.selectedTimeslot.day = false; 11640 this.selectedTimeslot.hours = false; 11641 this.selectedTimeslot.minutes = false; 11642 }, 11643 11644 displayAlert: function(message, type) { 11645 var message_html = '<div class="alert alert-'+type+'"><a class="close" href="#" data-dismiss="alert">×</a>'+message+'</div>'; 11646 $('.hf-cal__cal-w-wrapper').prepend(message_html); 11647 }, 11648 11649 populateAddresses: function(data) { 11650 // the format is: 11651 // {"line1","line2","line3","line4","locality","Town/City","County"} 11652 this.addresses = []; 11653 for (var i=0; i<data.Addresses.length; i++) { 11654 cleanedAddress = this.sanitizeAddress(data.Addresses[i]) 11655 this.addresses.push(cleanedAddress); 11656 } 11657 }, 11658 11659 sanitizeAddress: function(rawAddress) { 11660 rawAddress = rawAddress.split(','); 11661 var cleanedAddress = ""; 11662 for (var j=0; j<rawAddress.length; j++) { 11663 if (rawAddress[j] != '' && rawAddress[j] != ' ') { 11664 cleanedAddress += rawAddress[j]; 11665 cleanedAddress += ','; 11666 } 11667 } 11668 return cleanedAddress.slice(0, -1); 11669 }, 11670 11671 getStartOfWeek: function(d) { 11672 var day = d.getDay(), 11673 diff = d.getDate() - day + (day == 0 ? -6:1); // adjust when day is sunday 11674 return new Date(d.setDate(diff)); 11675 }, 11676 11677 buildMonth: function(month, year) { 11678 // get the first and last day of the month 11679 // this should always build the currently selected month 11680 var date = new Date(year, month); 11681 11682 var firstOfMonth = new Date(date.getFullYear(), month, 1); 11683 var lastOfMonth = new Date(date.getFullYear(), month + 1, 0); 11684 11685 var monthData = []; 11686 11687 // clone the date so we're not changing the original object 11688 var dayPointer = new Date(firstOfMonth.getTime()); 11689 11690 while (dayPointer.getDay() != 1) { 11691 // its not a monday, we need days from previous month 11692 monthData.unshift(dayPointer); 11693 dayPointer = new Date(dayPointer.setDate(dayPointer.getDate() - 1)); 11694 } 11695 11696 var currentDay = new Date(firstOfMonth.getTime()); 11697 11698 while (currentDay.getMonth() == month) { 11699 monthData.push(new Date(currentDay)); 11700 currentDay.setDate(currentDay.getDate() + 1); 11701 } 11702 11703 dayPointer = new Date(lastOfMonth.getTime()); 11704 11705 // sunday is 0 - convert first so it is 7 11706 var correctOrderDay = dayPointer.getDay() == 0 ? 7 : dayPointer.getDay(); 11707 11708 // while day is less than sunday 11709 while (correctOrderDay < 7) { 11710 monthData.push(dayPointer); 11711 dayPointer = new Date(dayPointer.setDate(dayPointer.getDate() + 1)); 11712 correctOrderDay++; 11713 } 11714 11715 return monthData; 11716 }, 11717 11718 selectWeek: function(e) { 11719 var $selected = $(e.currentTarget); 11720 var day = $selected.data('date-day'); 11721 var month = $selected.data('date-month'); 11722 var year = $selected.data('date-year'); 11723 var weekIndex = $selected.data('date-weekindex'); 11724 11725 this.wcDate = this.getStartOfWeek(new Date(year, month, day)); 11726 this.selectedWeek = parseInt(weekIndex); 11727 11728 this.getDates(); 11729 }, 11730 11731 selectTimeslot: function(e) { 11732 var $selected = $(e.currentTarget); 11733 var day = $selected.data('slot-day'); 11734 var minutes = $selected.data('slot-minutes'); 11735 var hours = $selected.data('slot-hours'); 11736 var month = $selected.data('slot-month'); 11737 var year = $selected.data('slot-year'); 11738 var duration = $selected.data('slot-duration'); 11739 11740 this.payload.chosenDate = $selected.data('slot-date'); 11741 this.payload.chosenTime = hours + ':' + minutes; 11742 this.payload.ownerId = $selected.data('slot-owner'); 11743 this.payload.ownerType = $selected.data('slot-owner-type'); 11744 this.payload.duration = $selected.data('slot-duration'); 11745 this.payload.justContactMe = false; 11746 if ($selected.hasClass('selected')) { 11747 this.selectedTimeslot = { 11748 day: false, 11749 hours: false, 11750 minutes: false, 11751 }; 11752 this.payload.chosenTime = false;
11753 this.payload.chosenDate = false; 11754 $selected.removeClass('selected'); 11755 } else { 11756 $('.hfview__timeslot').removeClass('selected'); 11757 $('.hfval__timeslot').removeClass('selected'); 11758 $selected.addClass('selected'); 11759 this.selectedTimeslot = { 11760 day: parseInt(day), 11761 hours: parseInt(hours), 11762 minutes: parseInt(minutes), 11763 month: parseInt(month), 11764 year: parseInt(year), 11765 } 11766 } 11767 }, 11768 11769 nextMonth: function() { 11770 this.wcDate.setMonth(this.wcDate.getMonth() + 1); 11771 this.calendarData.currentMonth = this.wcDate.getMonth(); 11772 11773 this.getDates(); 11774 }, 11775 11776 prevMonth: function() { 11777 this.wcDate.setMonth(this.wcDate.getMonth() - 1); 11778 this.calendarData.currentMonth = this.wcDate.getMonth(); 11779 11780 this.getDates(); 11781 }, 11782 11783 nextWeek: function() { 11784 if ( ($(window).width() <= 1024) && (!this.isInViewport($("#Sunday")[0])) ) { 11785 this.nextDay(); 11786 } else { 11787 this.wcDate.setDate(this.wcDate.getDate() + 7); 11788 this.calendarData.currentMonth = this.wcDate.getMonth(); 11789 this.selectedWeek = false; 11790 11791 this.getDates(); 11792 } 11793 }, 11794 11795 prevWeek: function() { 11796 if ( ($(window).width() <= 1024) && (!this.isInViewport($("#Monday")[0])) ) { 11797 this.prevDay(); 11798 } else { 11799 this.wcDate.setDate(this.wcDate.getDate() - 7); 11800 this.calendarData.currentMonth = this.wcDate.getMonth(); 11801 this.selectedWeek = false; 11802 11803 this.getDates(); 11804 } 11805 }, 11806 11807 nextDay: function() { 11808 day_element = $(".hf-cal__cal-w-days"); 11809 time_element = $(".hf-cal__cal-w-row"); 11810 width = -$(".hf-cal__cal-w-calendar")[0].clientWidth - 4 11811 currentLeft = $(".hf-cal__cal-w-days").css("left"); 11812 value = (width + parseInt(currentLeft)) + "px" 11813 day_element.css('left',value) 11814 time_element.css('left',value) 11815 sunday = $("#Sunday")[0]; 11816 monday = $("#Monday")[0]; 11817 if (this.isInViewport(sunday)) { 11818 $(".hf-cal__calendar-arrow--next.nextday").attr("id","hfval__nextweek"); 11819 } else { 11820 $(".hf-cal__calendar-arrow--next.nextday").attr("id","hfval__nextday"); 11821 } 11822 if (this.isInViewport(monday)) { 11823 $(".hf-cal__calendar-arrow--prev.prevday").attr("id","hfval__prevweek"); 11824 } else { 11825 $(".hf-cal__calendar-arrow--prev.prevday").attr("id","hfval__prevday"); 11826 } 11827 }, 11828 11829 prevDay: function() { 11830 day_element = $(".hf-cal__cal-w-days"); 11831 time_element = $(".hf-cal__cal-w-row"); 11832 width = $(".hf-cal__cal-w-calendar")[0].clientWidth + 4 11833 currentLeft = $(".hf-cal__cal-w-days").css("left"); 11834 value = (width + parseInt(currentLeft)) + "px" 11835 day_element.css('left',value) 11836 time_element.css('left',value) 11837 monday = $("#Monday")[0]; 11838 if (this.isInViewport(monday)) { 11839 $(".hf-cal__calendar-arrow--prev.prevday").attr("id","hfval__prevweek"); 11840 } else { 11841 $(".hf-cal__calendar-arrow--prev.prevday").attr("id","hfval__prevday"); 11842 } 11843 }, 11844 11845 getValuationOffice: function(office) { 11846 var customOffice = Ctesius.getConfig('CustomOffice'); 11847 if(customOffice){ 11848 return customOffice; 11849 } else { 11850 return office; 11851 } 11852 }, 11853 11854 getViewingOffice: function(office) { 11855 var customOffice = Ctesius.getConfig('CustomOffice'); 11856 if(customOffice){ 11857 return customOffice; 11858 } else { 11859 return office; 11860 } 11861 }, 11862 11863 getCustomValuationMessage: function(){ 11864 var customValuationMessage = Ctesius.getConfig('CustomValuationMessage'); 11865 if(customValuationMessage){ 11866 return customValuationMessage; 11867 } else { 11868 return undefined; 11869 } 11870 }, 11871 11872 getCustomViewingMessage: function(){ 11873 var customViewingMessage = Ctesius.getConfig('CustomViewingMessage'); 11874 if(customViewingMessage){ 11875 return customViewingMessage; 11876 } else { 11877 return undefined; 11878 } 11879 }, 11880 11881 propertyDescriptionText: function() { 11882 var propertyDescriptionText = Ctesius.getConfig('rda_property_desc_text'); 11883 if(propertyDescriptionText){ 11884 return propertyDescriptionText; 11885 } else { 11886 return 'Please provide as much detail about the property as possible'; 11887 } 11888 }, 11889 11890 getCurrentMonth: function(timeSlot){ 11891 var month = timeSlot.month; 11892 var monthNames = ["January", "February", "March", "April", "May", "June",
11893 "July", "August", "September", "October", "November", "December" 11894 ]; 11895 return monthNames[month] 11896 }, 11897 11898 /** 11899 * @name getCurrentDay 11900 * @description Gets the current day with full date format and returns each time value 11901 * @returns fullDate,day,month,year 11902 */ 11903 getCurrentDay: function() { 11904 var fullDate = new Date(); 11905 let day = fullDate.getDate(); 11906 let month = fullDate.getMonth(); 11907 let year = fullDate.getFullYear(); 11908 return {fullDate,day,month,year} 11909 }, 11910 11911 getTodayDayDate: function() { 11912 var t = new Date(); 11913 return t.getDate(); 11914 }, 11915 11916 getNextDay: function() { 11917 t = new Date(); 11918 var nextDay = [t.getFullYear(),(('0' + t.getMonth()).slice(-2)),(t.getDate()+10)+1].join('-'); 11919 return nextDay 11920 }, 11921 11922 getCurrentTime: function() { 11923 t = new Date(); 11924 mins = ('0'+ t.getMinutes()).slice(-2); 11925 var time = [t.getHours()+10,mins].join(':'); 11926 return time 11927 }, 11928 11929 bufferTime: function () { 11930 var bufferTime = new Date().addHours(36); 11931 return bufferTime 11932 }, 11933 11934 bufferDay: function () { 11935 var bufferTime = this.bufferTime(); 11936 var bufferDay = [bufferTime.getFullYear(), ('0' + bufferTime.getMonth()).slice(-2), (bufferTime.getDate() + 10)].join('-') 11937 return bufferDay 11938 }, 11939 11940 bufferClockTime: function () { 11941 var bufferTime = this.bufferTime(); 11942 var bufferClockTime = [bufferTime.getHours()+10, ('0' + bufferTime.getMinutes()).slice(-2)].join(':') 11943 return bufferClockTime 11944 }, 11945 11946 isInViewport: function (el) { 11947 var bounding = el.getBoundingClientRect(); 11948 return ( 11949 bounding.top >= 0 && 11950 bounding.left >= 0 && 11951 bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) && 11952 bounding.right <= (window.innerWidth || document.documentElement.clientWidth) 11953 ) 11954 }, 11955 11956 //refactor these 2 into 1 function 11957 toggleMarketingOptionVal: function () { 11958 ele = $('#hf-cal__valstep4__optin') 11959 val = $('#hf-cal__valstep4__optin').val(); 11960 if (val === '1') { 11961 ele.val('0') 11962 ele.prop('checked', false) 11963 } else { 11964 ele.val('1') 11965 ele.prop('checked', true) 11966 } 11967 new_val = $('#hf-cal__valstep4__optin').val(); 11968 this.toggleMarketingStatement(new_val); 11969 }, 11970 11971 toggleMarketingOptionView: function () { 11972 ele = $('#hf-cal__viewstep3__optin') 11973 val = $('#hf-cal__viewstep3__optin').val(); 11974 if (val === '1') { 11975 ele.val('0') 11976 ele.prop('checked', false) 11977 } else { 11978 ele.val('1') 11979 ele.prop('checked', true) 11980 } 11981 new_val = $('#hf-cal__viewstep3__optin').val(); 11982 this.toggleMarketingStatementView(new_val); 11983 }, 11984 11985 toggleTermsAndConditions: function (){ 11986 ele = $('#hf-cal__valstep4__tandcs') 11987 val = $('#hf-cal__valstep4__tandcs').val(); 11988 if (val === '1') { 11989 ele.val('0') 11990 ele.prop('checked', false) 11991 } else { 11992 ele.val('1') 11993 ele.prop('checked', true) 11994 } 11995 }, 11996 11997 toggleTermsAndConditionsView: function(){ 11998 ele = $('#hf-cal__viewstep3__tandcs'); 11999 val = $('#hf-cal__viewstep3__tandcs').val(); 12000 if (val === '1') { 12001 ele.val('0') 12002 ele.prop('checked', false) 12003 } else { 12004 ele.val('1') 12005 ele.prop('checked', true) 12006 } 12007 }, 12008 12009 toggleMarketingStatement: function (val){ 12010 statement_val = $('#hf-cal__valstep4__tandcs')[0].nextElementSibling.innerText; 12011 el = $('#hf-cal__valstep4__optin_statement'); 12012 val === '1' ? el.attr('value', statement_val) : el.attr('value', '') 12013 }, 12014 12015 toggleMarketingStatementView: function (val){ 12016 statement_val = $('#hf-cal__viewstep3__tandcs')[0].nextElementSibling.innerText; 12017 el = $('#hf-cal__viewstep3__optin_statement'); 12018 val === '1' ? el.attr('value', statement_val) : el.attr('value', '') 12019 }, 12020 12021 addBranchDetails: function (payload, data) { 12022 payload.branchId = data.branch_id; 12023 payload.branch = data.branch; 12024 } 12025 12026}; 12027 12028(function() { 12029window["JST"] = window["JST"] || {}; 12030 12031window["JST"]["view_step1.html"] = function(obj) { 12032obj || (obj = {}); 12033var __t, __p = ''; 12034with (obj) { 12035__p += '<div class="hf-cal__page hf-cal__view-step-1 ">\n\n <h2 class="hf-cal__page-title">\n ' + 12036((__t = ( ctaText )) == null ? '' : __t) + 12037'\n </h2>\n\n <div class="hf-cal__fw-image" style="background-image: url(' + 12038((__t = ( property.image )) == null ? '' : __t) + 12039');"> </div>\n\n <div class="hf-cal__property-info">\n <p class="hf-cal__property-info__address">\n ' + 12040((__t = ( property.address )) == null ? '' : __t) + 12041'\n </p>\n <p class="hf-cal__property-info__price">\n ' + 12042((__t = ( property.price )) == null ? '' : __t) + 12043'\n </p>\n </div>\n <p class="hf-cal__enter_email_text">To <span class="hf-cal__lowercase">' + 12044((__t = ( ctaText )) == null ? '' : __t) + 12045'</span> on this property, please enter your email address</p>\n\n <form class="hf-cal__form hfview__form">\n\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Email:\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input id="hf-cal__viewstep1__email-address" class="hf-cal__form-input hf-cal__form-input--text"\n placeholder="[email protected]" type="email" name="email" data-hfviewing="email" value="' + 12046((__t = ( email )) == null ? '' : __t) + 12047'" />\n </div>\n </div>\n\n <div class="hf-cal__form-submit">\n <button type="submit" class="hf-cal__form-button">\n ' + 12048((__t = ( buttonText )) == null ? '' : __t) + 12049'\n </button>\n </div>\n\n </form>\n</div>\n'; 12050 12051} 12052return __p 12053}})(); 12054(function() { 12055window["JST"] = window["JST"] || {}; 12056 12057window["JST"]["view_step2.html"] = function(obj) { 12058obj || (obj = {}); 12059var __t, __p = '', __j = Array.prototype.join; 12060function print() { __p += __j.call(arguments, '') } 12061with (obj) { 12062__p += '<!--calendar page -->\n<div class="hf-cal__page hf-cal__page-3">\n <div class="hf-cal__page hf-cal__page--step-3">\n <div class="hf-cal__calendar">\n\n <div class="hf-cal__calendar-left">\n <div class="hf-cal__calendar-intro">\n <p>' + 12063((__t = ( introText )) == null ? '' : __t) + 12064'</p>\n <a href="javascript:void(0);" id="hfview__just-contact-me" class="hf-cal__form-button hf-cal__form-button--inline">Just\n contact me</a>\n </div>\n\n <div class="hf-cal__cal-m-wrapper">\n <div class="hf-cal__cal-m-header">\n <a href="javascript:void(0);" class="hf-cal__calendar-arrow hf-cal__calendar-arrow--next-month" id="hfview__nextmonth"></a>\n '; 12065 var k = 0 ; 12066__p += '\n <!-- Calendar should not go past before the current month -->\n '; 12067 if (monthData[k].getMonth() != 0) { ; 12068__p += '\n <a href="javascript:void(0);" class="hf-cal__calendar-arrow hf-cal__calendar-arrow--prev-month" id="hfview__prevmonth"></a>\n '; 12069 } ; 12070__p += '\n '; 12071 var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] ;
12072__p += '\n <span>' + 12073((__t = ( months[currentMonth] )) == null ? '' : __t) + 12074' ' + 12075((__t = ( monthData[10].getFullYear() )) == null ? '' : __t) + 12076'</span>\n </div>\n <div class="hf-cal__cal-m-calendar">\n <div class="hf-cal__cal-m-days">\n <span class="hf-cal__cal-m-day">M</span>\n <span class="hf-cal__cal-m-day">T</span>\n <span class="hf-cal__cal-m-day">W</span>\n <span class="hf-cal__cal-m-day">T</span>\n <span class="hf-cal__cal-m-day">F</span>\n <span class="hf-cal__cal-m-day">S</span>\n <span class="hf-cal__cal-m-day">S</span>\n </div>\n <div class="hf-cal__cal-m-grid">\n '; 12077 for (var i=0; i<6; i++) { ; 12078__p += '\n <div class="hf-cal__cal-m-row '; 12079 if (selectedWeek === i) { ; 12080__p += 'selected'; 12081 } ; 12082__p += '">\n '; 12083 for (var j=0; j<7; j++) { ; 12084__p += '\n '; 12085 if (monthData[k]) { ; 12086__p += '\n <!-- First condition here displays the current day on calendar -->\n '; 12087 if (monthData[k].getMonth() == currentDay.month && currentDay.day == monthData[k].getDate()) { ; 12088__p += '\n <div style="font-weight: bold;" class="hf-cal__cal-m-cell hfview__month--day" data-date-day="' + 12089((__t = ( monthData[k].getDate() )) == null ? '' : __t) + 12090'"\n data-date-month="' + 12091((__t = ( monthData[k].getMonth() )) == null ? '' : __t) + 12092'" data-date-year="' + 12093((__t = ( monthData[k].getFullYear() )) == null ? '' : __t) + 12094'"\n data-date-weekindex="' + 12095((__t = ( i )) == null ? '' : __t) + 12096'">\n '; 12097 if (monthData[k].getMonth() == currentMonth) { ; 12098__p += '\n ' + 12099((__t = ( monthData[k].getDate() )) == null ? '' : __t) + 12100'\n '; 12101 } ; 12102__p += '\n </div>\n <!-- Makes the the previous days before today or days displaying from previous month not selectable -->\n '; 12103 } else if (monthData[k].getMonth() == currentDay.month && currentDay.day > monthData[k].getDate() || monthData[k].getMonth() < currentDay.month) { ; 12104__p += '\n <div style="color: lightgray; pointer-events: none;" class="hf-cal__cal-m-cell hfview__month--day" data-date-day="' + 12105((__t = ( monthData[k].getDate() )) == null ? '' : __t) + 12106'"\n data-date-month="' + 12107((__t = ( monthData[k].getMonth() )) == null ? '' : __t) + 12108'" data-date-year="' + 12109((__t = ( monthData[k].getFullYear() )) == null ? '' : __t) + 12110'"\n data-date-weekindex="' + 12111((__t = ( i )) == null ? '' : __t) + 12112'">\n '; 12113 if (monthData[k].getMonth() == currentMonth) { ; 12114__p += '\n ' + 12115((__t = ( monthData[k].getDate() )) == null ? '' : __t) + 12116'\n '; 12117 } ; 12118__p += '\n </div>\n <!-- Today and days after today should be selectable -->\n '; 12119 } else { ; 12120__p += '\n <div class="hf-cal__cal-m-cell hfview__month--day" data-date-day="' + 12121((__t = ( monthData[k].getDate() )) == null ? '' : __t) + 12122'"\n data-date-month="' + 12123((__t = ( monthData[k].getMonth() )) == null ? '' : __t) + 12124'" data-date-year="' + 12125((__t = ( monthData[k].getFullYear() )) == null ? '' : __t) + 12126'"\n data-date-weekindex="' + 12127((__t = ( i )) == null ? '' : __t) + 12128'">\n '; 12129 if (monthData[k].getMonth() == currentMonth) { ; 12130__p += '\n ' + 12131((__t = ( monthData[k].getDate() )) == null ? '' : __t) + 12132'\n '; 12133 } ; 12134__p += '\n </div>\n '; 12135 } ; 12136__p += '\n '; 12137 } else { ; 12138__p += '\n <div class="hf-cal__cal-m-cell hfval__month--day"></div>\n '; 12139 } ; 12140__p += '\n '; 12141 k++ ; 12142__p += '\n '; 12143 } ; 12144__p += '\n </div>\n '; 12145 } ; 12146__p += '\n </div>\n </div>\n </div>\n </div>\n <div class="hf-cal__calendar-right">\n <div class="hf-cal__cal-w-wrapper">\n <div class="hf-cal__cal-w-calendar">\n <a href="javascript:void(0);" class="hf-cal__calendar-arrow hf-cal__calendar-arrow--next nextday" id="hfview__nextweek"></a>\n <!-- Previous week should not be selected to pick a slot on time table for current week, but for coming weeks that should be a previous weeks button -->\n '; 12147 if (wcDate > currentDay.fullDate) { ; 12148__p += '\n <a href="javascript:void(0);" class="hf-cal__calendar-arrow hf-cal__calendar-arrow--prev prevday" id="hfview__prevweek"></a>\n '; 12149 } ; 12150__p += '\n <div class="hf-cal__cal-w-days">
12150\n <span class="hf-cal__cal-w-day" id="Monday">Mon ' + 12151((__t = ( days.appointments[0].d )) == null ? '' : __t) + 12152'</span>\n <span class="hf-cal__cal-w-day" id="Tuesday">Tues ' + 12153((__t = ( days.appointments[1].d )) == null ? '' : __t) + 12154'</span>\n <span class="hf-cal__cal-w-day" id="Wednesday">Wed ' + 12155((__t = ( days.appointments[2].d )) == null ? '' : __t) + 12156'</span>\n <span class="hf-cal__cal-w-day" id="Thursday">Thurs ' + 12157((__t = ( days.appointments[3].d )) == null ? '' : __t) + 12158'</span>\n <span class="hf-cal__cal-w-day" id="Friday">Fri ' + 12159((__t = ( days.appointments[4].d )) == null ? '' : __t) + 12160'</span>\n <span class="hf-cal__cal-w-day" id="Saturday">Sat ' + 12161((__t = ( days.appointments[5].d )) == null ? '' : __t) + 12162'</span>\n <span class="hf-cal__cal-w-day" id="Sunday">Sun ' + 12163((__t = ( days.appointments[6].d )) == null ? '' : __t) + 12164'</span>\n </div>\n <div class="hf-cal__cal-w-grid">\n <div class="hf-cal__cal-w-row">\n '; 12165 for (var i=0; i<days.appointments.length; i++) { ; 12166__p += '\n '; 12167 var day = days.appointments[i] ; 12168__p += '\n '; 12169 var slotDay = [day.y,('0' + day.m).slice(-2),day.d+10].join('-') ; 12170__p += '\n <div class="hf-cal__cal-w-col">\n '; 12171 if (day.slots) { ; 12172__p += '\n '; 12173 for (var j=0; j<day.slots.length; j++) { ; 12174__p += '\n '; 12175 var slot = day.slots[j] ; 12176__p += '\n '; 12177 var slotTime = [slot.hours+10,slot.minutes].join(':') ; 12178__p += '\n <div class="hf-cal__cal-w-cell">\n <a href="javascript:void(0);"\n class="hf-cal__cal-w-button '; 12179 if ( (!hfOnlyCal && slot.available == 0) || ((slotDay < bufferDay) && hfOnlyCal) || ((slotDay == bufferDay) && (slotTime <= buffer) && hfOnlyCal)) { ; 12180__p += 'unavailable'; 12181 } ; 12182__p += ' '; 12183 if (selectedTimeslot.day == day.d && selectedTimeslot.hours == slot.hours && selectedTimeslot.minutes == slot.minutes) { ; 12184__p += 'selected'; 12185 } ; 12186__p += ' hfview__timeslot"\n data-slot-date="' + 12187((__t = ( day.y )) == null ? '' : __t) + 12188'-' + 12189((__t = ( day.m )) == null ? '' : __t) + 12190'-' + 12191((__t = ( day.d )) == null ? '' : __t) + 12192'"\n data-slot-month="' + 12193((__t = ( day.m )) == null ? '' : __t) + 12194'"\n data-slot-year="' + 12195((__t = ( day.y )) == null ? '' : __t) + 12196'"\n data-slot-hours="' + 12197((__t = ( slot.hours )) == null ? '' : __t) + 12198'"\n data-slot-minutes="' + 12199((__t = ( slot.minutes )) == null ? '' : __t) + 12200'"\n data-slot-day="' + 12201((__t = ( day.d )) == null ? '' : __t) + 12202'"\n data-slot-time="' + 12203((__t = ( slot.hours )) == null ? '' : __t) + 12204':' + 12205((__t = ( slot.minutes )) == null ? '' : __t) + 12206'"\n data-slot-owner="' + 12207((__t = ( slot.owner_id )) == null ? '' : __t) + 12208'"\n data-slot-owner-type="' + 12209((__t = ( slot.owner_type )) == null ? '' : __t) + 12210'"\n data-slot-duration="' + 12211((__t = ( slot.duration )) == null ? '' : __t) + 12212'">\n ' + 12213((__t = ( slot.hours )) == null ? '' : __t) + 12214':' + 12215((__t = ( slot.minutes )) == null ? '' : __t) + 12216'\n </a>\n </div>\n '; 12217 } ; 12218__p += '\n '; 12219 } ; 12220__p += '\n </div>\n '; 12221 } ; 12222__p += '\n </div>\n </div>\n </div>\n </div>\n\n <div class="hf-cal__form-section hf-cal__form-section--calendar">\n <form class="hf-cal__form hfview__form">\n <div class="hf-cal__form-submit hf-cal__form-submit--calendar">\n <button class="hf-cal__back hfview__back">Back</button>\n <button type="submit" class="hf-cal__form-button hf-cal__form-button--inline">Next</button>\n </div>\n </form>\n </div>\n\n </div>\n </div>\n\n </div>\n</div>\n<!-- end calendar page -->\n'; 12223 12224} 12225return __p 12226}})(); 12227(function() { 12228window["JST"] = window["JST"] || {}; 12229 12230window["JST"]["view_step3.html"] = function(obj) { 12231obj || (obj = {}); 12232var __t, __p = '', __j = Array.prototype.join; 12233function print() { __p += __j.call(arguments, '') } 12234with (obj) { 12235__p += '<div class="hf-cal__page hf-cal__view-step-3">\n <h2 class="hf-cal__page-title hf-cal__flex-pad">Your Details</h2>\n <div class="hf-cal__form-section">\n <form class="hf-cal__form hf-cal__form__flex hfview__form">\n '; 12236 if (uses_salutation) { ; 12237__p += '\n <div class="hf-cal_salutation">\n <div class="hf-cal__form-label">\n Title*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text hf-cal__form-element--title">\n <select\n id="hf-cal__viewstep3__title"\n class="hf-cal__form-input hf-cal__form-input--text hfview__input hf-cal__form-input--sal"\n type="text"\n name="title-name_param"\n data-hfviewing="title"\n autofocus\n >\n <option value="Mr">Mr</option>\n <option value="Sir">Sir</option>\n <option value="Mrs">Mrs</option>\n <option value="Miss">Miss</option>\n <option value="Ms">Ms</option>\n <option value="Dr">Dr</option>\n <option value="Prof">Prof</option>\n </select>\n </div>\n </div>\n '; 12238 } ; 12239__p += '\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n First Name*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__viewstep3__first-name"\n class="hf-cal__form-input hf-cal__form-input--text hfview__input required"\n type="text"\n name="first-name_param"\n data-hfviewing="first-name"\n required\n '; 12240 if (firstName !== 'Guest') { ; 12241__p += '\n value="' + 12242((__t = ( firstName )) == null ? '' : __t) + 12243'"\n '; 12244 } ; 12245__p += '\n autofocus\n />\n </div>\n </div>\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Surname*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__viewstep3__surname"\n class="hf-cal__form-input hf-cal__form-input--text hfview__input required"\n name="surname_param"\n data-hfviewing="last-name"\n value="' + 12246((__t = ( lastName )) == null ? '' : __t) + 12247'"\n required\n />\n </div>\n </div>\n <div class="hf-cal__form__flex"> <!-- address section -->\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n House Name\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__viewstep3__first-name"\n class="hf-cal__form-input hf-cal__form-input--text hfview__input"\n type="text"\n name="house-name_param"\n data-hfviewing-address="building-name"\n value="' + 12248((__t = ( house_name )) == null ? '' : __t) + 12249'"\n />\n </div>\n </div>\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n House Number\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__viewstep3__surname"\n class="hf-cal__form-input hf-cal__form-input--text hfview__input"\n name="house-number_param"\n data-hfviewing-address="building-reference"\n value="' + 12250((__t = ( house_number )) == null ? '' : __t) + 12251'"\n />\n </div>\n </div>\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Street*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__viewstep3__street"\n class="hf-cal__form-input hf-cal__form-input--text hfview__input required"\n type="text"\n name="street_param"\n data-hfviewing-address="street"\n value="' + 12252((__t = ( street )) == null ? '' : __t) + 12253'"\n required\n />\n </div>\n </div>\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Locality\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__viewstep3__locality"\n class="hf-cal__form-input hf-cal__form-input--text hfview__input"\n type="text"\n name="locality_param"\n data-hfviewing-address="locality"\n value="' + 12254((__t = ( locality )) == null ? '' : __t) + 12255'"\n />\n </div>\n </div>\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Town*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__viewstep3__town"\n class="hf-cal__form-input hf-cal__form-input--text hfview__input required"\n type="text"\n name="town_param"\n data-hfviewing-address="town"\n value="' + 12256((__t = ( town )) == null ? '' : __t) + 12257'"\n required\n />\n </div>\n </div>\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n County\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">
12257\n <input\n id="hf-cal__viewstep3__county"\n class="hf-cal__form-input hf-cal__form-input--text hfview__input"\n type="text"\n name="county_param"\n data-hfviewing-address="county"\n value="' + 12258((__t = ( county )) == null ? '' : __t) + 12259'"\n />\n </div>\n </div>\n <div class="hf-cal__form-group hf-cal__form-group__postcode--viewing">\n <div class="hf-cal__form-label">\n Postcode*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text calendar-postcode">\n <input\n id="hf-cal__viewstep3__postcode"\n class="hf-cal__form-input hf-cal__form-input--text required"\n type="text"\n name="postcode_param"\n data-hfviewing-address="postcode"\n value="' + 12260((__t = ( postcode )) == null ? '' : __t) + 12261'"\n required\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group__phone">\n <div class="hf-cal__form-label">\n Telephone*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__viewstep3__telephone"\n class="hf-cal__form-input hf-cal__form-input--text hfview__input"\n type="tel"\n name="telephone_param"\n data-hfviewing="phone"\n value="' + 12262((__t = ( phone )) == null ? '' : __t) + 12263'"\n required\n pattern="^[0-9-.()\\/ +]{6,20}$"\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group__phone">\n <div class="hf-cal__form-label">\n Mobile*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__viewstep3__mobile"\n class="hf-cal__form-input hf-cal__form-input--text hfview__input"\n type="mobile"\n name="mobile_param"\n data-hfviewing="mobile"\n value="' + 12264((__t = ( mobile )) == null ? '' : __t) + 12265'"\n required\n pattern="^[0-9-.()\\/ +]{6,20}$"\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group__full-width">\n <div class="hf-cal__form-element">\n <div class="hf-cal__form-label">\n Email*\n </div>\n <input\n id="hf-cal__viewstep3__email-address"\n class="hf-cal__form-input hf-cal__form-input--text hfview__input required"\n placeholder="[email protected]"\n type="email"\n name="email"\n data-hfviewing="email"\n value="' + 12266((__t = ( userEmail )) == null ? '' : __t) + 12267'"\n required\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group__full-width">\n <div class="hf-cal__form-label">\n Message\n </div>\n <textarea\n id="hf-cal__viewstep3__details"\n class="hf-cal__form-input hf-cal__form-input--text"\n name="details_param"\n data-hfviewing="notes"\n >' + 12268((__t = ( notes )) == null ? '' : __t) + 12269'</textarea>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group__full-width">\n <div class="hf-cal__form-label">\n I am looking to:\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--radio-group">\n <label for="hf-cal__viewstep3__intention--buy" class="hf-cal__radio-button">\n <input\n id="hf-cal__viewstep3__intention--buy"\n class="hf-cal__radio-input hfview__intention"\n value="sell"\n type="radio"\n name="intention"\n data-hfviewing-intention="intention"\n >
12269\n <span class="hf-cal__span-label hf-cal__radio-label">Sell</span>\n </label>\n <label for="hf-cal__viewstep3__intention--rent" class="hf-cal__radio-button">\n <input\n id="hf-cal__viewstep3__intention--rent"\n class="hf-cal__radio-input hfview__intention"\n value="let"\n type="radio"\n name="intention"\n data-hfviewing-intention="intention"\n >\n <span class="hf-cal__span-label hf-cal__radio-label">Let</span>\n </label>\n <label for="hf-cal__viewstep3__intention--neither" class="hf-cal__radio-button">\n <input\n id="hf-cal__viewstep3__intention--neither"\n class="hf-cal__radio-input hfview__intention"\n value="neither"\n type="radio"\n name="intention"\n data-hfviewing-intention="intention"\n >\n <span class="hf-cal__span-label hf-cal__radio-label">Neither</span>\n </label>\n </div>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group__opt-in hf-cal__form-group__full-width">\n <div class="hf-cal__form-element hf-cal__form-element--radio-group">\n <input\n id="hf-cal__viewstep3__optin"\n class="hf-cal__radio-input"\n value="0"\n type="checkbox"\n name="mailOptIn"\n data-hfviewing="mail-optin"\n >\n <span onclick="" id="hf-cal__viewstep3__optin_label" class="hf-cal__span-label hf-cal__radio-label">Opt in for marketing communications. View <a class="hf-cal__link" href="/pages/terms-of-use" target="_blank">Terms\n & Conditions</a> and <a class="hf-cal__link" href="/pages/privacy-policy" target="_blank">\n Privacy Policy</a>. </span>\n </div>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group__opt-in hf-cal__form-group__full-width">\n <div class="hf-cal__form-element hf-cal__form-element--radio-group">\n <input\n id="hf-cal__viewstep3__tandcs"\n class="hf-cal__radio-input"\n value="0"\n type="checkbox"\n name="termsAndConditions"\n data-hfviewing="terms_and_conditions"\n required\n >\n <span onclick="" id="hf-cal__viewstep3__tandcs_label" class="hf-cal__span-label hf-cal__radio-label">I have read and agree to the Terms and Conditions, Privacy Policy and Cookies\n Policy*</span>\n </div>\n\n <input\n hidden\n id="hf-cal__viewstep3__optin_statement"\n name="optInStatement"\n value=""\n data-hfviewing="optin_statement"\n >\n\n <div class="hf-cal__form-submit hf-cal__form-group__full-width hf-cal__flex-pad">\n <button class="hf-cal__back hfview__back">Back</button>\n <button type="submit" class="hf-cal__form-button">Request</button>\n </div>\n </form>\n </div> <!-- end hf-cal__form-section -->\n</div>\n'; 12270 12271} 12272return __p 12273}})(); 12274(function() { 12275window["JST"] = window["JST"] || {}; 12276 12277window["JST"]["view_step4.html"] = function(obj) { 12278obj || (obj = {}); 12279var __t, __p = '', __j = Array.prototype.join; 12280function print() { __p += __j.call(arguments, '') } 12281with (obj) { 12282__p += '<div class="hf-cal__page hf-cal__view-step-4 hf-cal__flex-fill">\n '; 12283 if (error) { ; 12284__p += '\n <h2 class="hf-cal__page-title ">Sorry, something went wrong</h2>\n\n <div class="hf-cal__text-section">\n <p>Please contact the ' + 12285((__t = ( office.name )) == null ? '' : __t) + 12286' branch on <a href="tel:' + 12287((__t = ( office.phonehref )) == null ? '' : __t) + 12288'">' + 12289((__t = ( office.phone )) == null ? '' : __t) + 12290'</a> or email <a href="maito:' + 12291((__t = ( office.email )) == null ? '' : __t) + 12292'">' + 12293((__t = ( office.email )) == null ? '' : __t) + 12294'</a> to arrange a viewing.</p>\n </div>\n '; 12295 } else { ; 12296__p += '\n <h2 class="hf-cal__page-title ">Viewing Requested</h2>\n <div class="hf-cal__fw-image" style="background-image: url(' + 12297((__t = ( property.image )) == null ? '' : __t) + 12298');"> </div>\n\n <div class="hf-cal__text-section">\n '; 12299 if (justContactMe) { ; 12300__p += '\n <p>Your viewing request for ' + 12301((__t = ( property.address )) == null ? '' : __t) + 12302' has been sent someone will be in touch to organise a time with you.</p>\n '; 12303 } else { ; 12304__p += '\n <p>Your viewing for ' + 12305((__t = ( property.address )) == null ? '' : __t) + 12306' has been requested for ' + 12307((__t = ( selectedTime.day )) == null ? '' : __t) + 12308'/' + 12309((__t = ( selectedTime.month + 1 )) == null ? '' : __t) + 12310'/' + 12311((__t = ( selectedTime.year )) == null ? '' : __t) + 12312' at ' + 12313((__t = ( ('0' + selectedTime.hours).slice(-2) )) == null ? '' : __t) + 12314':' + 12315((__t = ( ('0' + selectedTime.minutes).slice(-2) )) == null ? '' : __t) + 12316'.</p>\n '; 12317 } ; 12318__p += '\n\n <p >If you have any queries or need to cancel or amend your appointment, please call the ' + 12319((__t = ( office.name )) == null ? '' : __t) + 12320' branch on <a href="tel:' + 12321((__t = ( office.phonehref )) == null ? '' : __t) + 12322'">' + 12323((__t = ( office.phone )) == null ? '' : __t) + 12324'</a> or email <a href="maito:' + 12325((__t = ( office.email )) == null ? '' : __t) + 12326'">' + 12327((__t = ( office.email )) == null ? '' : __t) + 12328'</a> </p>\n </div>\n '; 12329 } ; 12330__p += '\n\n <div class="hf-cal__form-submit ">\n <button class="hf-cal__form-button" id="hfview__done-btn">Done</button>\n </div> \n</div>'; 12331 12332} 12333return __p 12334}})(); 12335(function() { 12336window["JST"] = window["JST"] || {}; 12337 12338window["JST"]["val_step1.html"] = function(obj) { 12339obj || (obj = {}); 12340var __t, __p = '', __j = Array.prototype.join; 12341function print() { __p += __j.call(arguments, '') } 12342with (obj) { 12343__p += '<!-- page one -->\n<div class="hf-cal__page hf-cal__page-1">\n <h2 class="hf-cal__page-title">Request a valuation</h2>\n <p class="hf-cal__page-subtitle">To book a valuation, please enter your email address</p>\n <div class="hf-cal__page hf-cal__page--step-1">\n <div class="hf-cal__form-section">\n <form class="hf-cal__form hfval__form">\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Looking to:\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--radio-group">\n <label for="hf-cal__channel--sales" class="hf-cal__radio-label hf-cal__radio-option">\n <input\n id="hf-cal__channel--sales"\n class="hf-cal__radio-input hfval__channel"\n value="sales"\n type="radio"\n name="channel"\n '; 12344 if (channel == 'sales') { ; 12345__p += '\n checked="checked"\n '; 12346 } ; 12347__p += '\n required\n />\n Sell a property\n </label>\n <label for="hf-cal__channel--lets" class="hf-cal__radio-label hf-cal__radio-option">\n <input\n id="hf-cal__channel--lets"\n class="hf-cal__radio-input hfval__channel"\n value="lettings"\n type="radio"\n name="channel"\n '; 12348 if (channel == 'lettings') { ; 12349__p += '\n checked="checked"\n '; 12350 } ; 12351__p += '\n required\n />\n Let a property\n </label>\n <label for="hf-cal__channel--both" class="hf-cal__radio-label hf-cal__radio-option">\n <input\n id="hf-cal__channel--both"\n class="hf-cal__radio-input hfval__channel"\n value="both"\n type="radio"\n name="channel"\n '; 12352 if (channel == 'both') { ; 12353__p += '\n checked="checked"\n '; 12354 } ; 12355__p += '\n required\n />\n Both\n </label>\n </div>\n </div>\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Email:\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">
12355\n <input\n id="hf-cal__email-address"\n class="hf-cal__form-input hf-cal__form-input--text"\n placeholder="[email protected]"\n type="email"\n name="email"\n data-hfbooking="email"\n value="' + 12356((__t = ( email )) == null ? '' : __t) + 12357'"\n required\n />\n </div>\n </div>\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Postcode:\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__postcode"\n class="hf-cal__form-input hf-cal__form-input--text"\n placeholder="Enter your postcode"\n type="postcode"\n name="postcode_param"\n data-hfbooking="postcode_param"\n pattern="^[a-zA-Z]{1,2}\\d[a-z\\d]?\\s*\\d[a-zA-Z]{2}$"\n value="' + 12358((__t = ( postcode )) == null ? '' : __t) + 12359'"\n required\n />\n </div>\n </div>\n <div class="hf-cal__form-submit">\n <button type="submit" class="hf-cal__form-button">Next</button>\n </div>\n </form>\n </div>\n </div>\n</div>\n<!-- end page one -->\n'; 12360 12361} 12362return __p 12363}})(); 12364(function() { 12365window["JST"] = window["JST"] || {}; 12366 12367window["JST"]["val_step2.html"] = function(obj) { 12368obj || (obj = {}); 12369var __t, __p = '', __j = Array.prototype.join; 12370function print() { __p += __j.call(arguments, '') } 12371with (obj) { 12372__p += '<!-- select address page -->\n<div class="hf-cal__page hf-cal__page-2">\n <h2 class="hf-cal__page-title">Select your address</h2>\n <p class="hf-cal__page-subtitle"></p>\n <div class="hf-cal__page hf-cal__page--step-2">\n <div class="hf-cal__form-section">\n <form class="hf-cal__form hfval__form">\n\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Select\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--select">\n <select id="hf-cal__select-address" class="hf-cal__form-select" name="select-address" data-hfbooking="address" required>\n <option value="">Select address</option>\n '; 12373 for (var i=0; i<addresses.length; i++) { ; 12374__p += '\n <option value="' + 12375((__t = ( rawAddresses[i] )) == null ? '' : __t) + 12376'">' + 12377((__t = ( addresses[i] )) == null ? '' : __t) + 12378'</option>\n '; 12379 } ; 12380__p += '\n </select>\n </div>\n </div>\n\n <div class="hf-cal__form-submit">\n <button class="hf-cal__back hfval__back">Back</button>\n <button type="submit" class="hf-cal__form-button">Next</button>\n </div>\n\n </form>\n </div>\n </div>\n</div>\n<!-- end select address page-->\n'; 12381 12382} 12383return __p 12384}})(); 12385(function() { 12386window["JST"] = window["JST"] || {}; 12387 12388window["JST"]["val_step3.html"] = function(obj) { 12389obj || (obj = {}); 12390var __t, __p = '', __j = Array.prototype.join; 12391function print() { __p += __j.call(arguments, '') } 12392with (obj) { 12393__p += '<!--calendar page -->\n<div class="hf-cal__page hf-cal__page-3">\n <div class="hf-cal__page hf-cal__page--step-3">\n\n <div class="hf-cal__calendar">\n\n <div class="hf-cal__calendar-left">\n <div class="hf-cal__calendar-intro">\n <p>Please choose a date and time you would like your valuation, if your desired time is not available then click the below and we will get in touch.</p>\n <a href="javascript:void(0);" id="hfval__just-contact-me" class="hf-cal__form-button hf-cal__form-button--inline">Just contact me</a>\n </div>\n\n <div class="hf-cal__cal-m-wrapper">\n <div class="hf-cal__cal-m-header">\n <a href="javascript:void(0);" class="hf-cal__calendar-arrow hf-cal__calendar-arrow--next-month" id="hfval__nextmonth"></a>\n <a href="javascript:void(0);" class="hf-cal__calendar-arrow hf-cal__calendar-arrow--prev-month" id="hfval__prevmonth"></a>\n '; 12394 var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] ;
12395__p += '\n <span>' + 12396((__t = ( months[currentMonth] )) == null ? '' : __t) + 12397' ' + 12398((__t = ( monthData[10].getFullYear() )) == null ? '' : __t) + 12399'</span>\n </div>\n <div class="hf-cal__cal-m-calendar">\n <div class="hf-cal__cal-m-days">\n <span class="hf-cal__cal-m-day">M</span>\n <span class="hf-cal__cal-m-day">T</span>\n <span class="hf-cal__cal-m-day">W</span>\n <span class="hf-cal__cal-m-day">T</span>\n <span class="hf-cal__cal-m-day">F</span>\n <span class="hf-cal__cal-m-day">S</span>\n <span class="hf-cal__cal-m-day">S</span>\n </div>\n <div class="hf-cal__cal-m-grid">\n '; 12400 var k = 0 ; 12401__p += '\n '; 12402 for (var i=0; i<6; i++) { ; 12403__p += '\n <div class="hf-cal__cal-m-row '; 12404 if (selectedWeek === i) { ; 12405__p += 'selected'; 12406 } ; 12407__p += '">\n '; 12408 for (var j=0; j<7; j++) { ; 12409__p += '\n '; 12410 if (monthData[k]) { ; 12411__p += '\n <div\n class="hf-cal__cal-m-cell hfval__month--day"\n data-date-day="' + 12412((__t = ( monthData[k].getDate() )) == null ? '' : __t) + 12413'"\n data-date-month="' + 12414((__t = ( monthData[k].getMonth() )) == null ? '' : __t) + 12415'"\n data-date-year="' + 12416((__t = ( monthData[k].getFullYear() )) == null ? '' : __t) + 12417'"\n data-date-weekindex="' + 12418((__t = ( i )) == null ? '' : __t) + 12419'"\n >\n '; 12420 if (monthData[k].getMonth() == currentMonth) { ; 12421__p += '\n ' + 12422((__t = ( monthData[k].getDate() )) == null ? '' : __t) + 12423'\n '; 12424 } ; 12425__p += '\n </div>\n '; 12426 } else { ; 12427__p += '\n <div class="hf-cal__cal-m-cell hfval__month--day"></div>\n '; 12428 } ; 12429__p += '\n '; 12430 k++ ; 12431__p += '\n '; 12432 } ; 12433__p += '\n </div>\n '; 12434 } ; 12435__p += '\n </div>\n </div>\n </div>\n </div>\n <div class="hf-cal__calendar-right">\n <div class="hf-cal__cal-w-wrapper">\n <div class="hf-cal__cal-w-calendar">\n <a href="javascript:void(0);" class="hf-cal__calendar-arrow hf-cal__calendar-arrow--next nextday" id="hfval__nextweek"></a>\n <a href="javascript:void(0);" class="hf-cal__calendar-arrow hf-cal__calendar-arrow--prev prevday" id="hfval__prevweek"></a>\n <div class="hf-cal__cal-w-days">\n\n <span class="hf-cal__cal-w-day" id="Monday">Mon ' + 12436((__t = ( days.appointments[0].d )) == null ? '' : __t) + 12437'</span>\n <span class="hf-cal__cal-w-day" id="Tuesday">Tues ' + 12438((__t = ( days.appointments[1].d )) == null ? '' : __t) + 12439'</span>\n <span class="hf-cal__cal-w-day" id="Wednesday">Wed ' + 12440((__t = ( days.appointments[2].d )) == null ? '' : __t) + 12441'</span>\n <span class="hf-cal__cal-w-day" id="Thursday">Thurs ' + 12442((__t = ( days.appointments[3].d )) == null ? '' : __t) + 12443'</span>\n <span class="hf-cal__cal-w-day" id="Friday">Fri ' + 12444((__t = ( days.appointments[4].d )) == null ? '' : __t) + 12445'</span>\n <span class="hf-cal__cal-w-day" id="Saturday">Sat ' + 12446((__t = ( days.appointments[5].d )) == null ? '' : __t) + 12447'</span>\n <span class="hf-cal__cal-w-day" id="Sunday">Sun ' + 12448((__t = ( days.appointments[6].d )) == null ? '' : __t) + 12449'</span>\n </div>\n <div class="hf-cal__cal-w-grid">\n\n <div class="hf-cal__cal-w-row">\n '; 12450 for (var i=0; i<days.appointments.length; i++) { ; 12451__p += '\n '; 12452 var day = days.appointments[i] ; 12453__p += '\n '; 12454 var slotDay = [day.y,('0' + day.m).slice(-2),day.d+10].join('-') ; 12455__p += '\n <div class="hf-cal__cal-w-col">\n '; 12456 if (day.slots) { ; 12457__p += '\n '; 12458 for (var j=0; j<day.slots.length; j++) { ; 12459__p += '\n '; 12460 var slot = day.slots[j] ; 12461__p += '\n '; 12462 var slotTime = [slot.hours+10,slot.minutes].join(':') ; 12463__p += '\n <div class="hf-cal__cal-w-cell">\n <a\n href="javascript:void(0);"\n class="hf-cal__cal-w-button '; 12464 if ( (!hfOnlyCal && slot.available == 0) || ((slotDay < bufferDay) && hfOnlyCal) || ((slotDay == bufferDay) && (slotTime <= buffer) && hfOnlyCal)) { ; 12465__p += 'unavailable'; 12466 } ; 12467__p += ' '; 12468 if (selectedTimeslot.day == day.d && selectedTimeslot.hours == slot.hours && selectedTimeslot.minutes == slot.minutes) { ; 12469__p += 'selected'; 12470 } ; 12471__p += ' hfval__timeslot"\n data-slot-date="' + 12472((__t = ( day.y )) == null ? '' : __t) + 12473'-' + 12474((__t = ( day.m )) == null ? '' : __t) + 12475'-' + 12476((__t = ( day.d )) == null ? '' : __t) + 12477'"\n data-slot-month="' + 12478((__t = ( day.m )) == null ? '' : __t) + 12479'"\n data-slot-year="' + 12480((__t = ( day.y )) == null ? '' : __t) + 12481'"\n data-slot-hours="' + 12482((__t = ( slot.hours )) == null ? '' : __t) + 12483'"\n data-slot-minutes="' + 12484((__t = ( slot.minutes )) == null ? '' : __t) + 12485'"\n data-slot-day="' + 12486((__t = ( day.d )) == null ? '' : __t) + 12487'"\n data-slot-time="' + 12488((__t = ( slot.hours )) == null ? '' : __t) + 12489':' + 12490((__t = ( slot.minutes )) == null ? '' : __t) + 12491'"\n data-slot-owner="' + 12492((__t = ( slot.owner_id )) == null ? '' : __t) + 12493'"\n data-slot-owner-type="' + 12494((__t = ( slot.owner_type )) == null ? '' : __t) + 12495'"\n data-slot-duration="' + 12496((__t = ( slot.duration )) == null ? '' : __t) + 12497'"\n >\n ' + 12498((__t = ( slot.hours )) == null ? '' : __t) + 12499':' + 12500((__t = ( slot.minutes )) == null ? '' : __t) + 12501'\n </a>\n </div>\n '; 12502 } ; 12503__p += '\n '; 12504 } ; 12505__p += '\n </div>\n '; 12506 } ; 12507__p += '\n </div>\n </div>\n </div>\n </div>\n\n <div class="hf-cal__form-section hf-cal__form-section--calendar">\n <form class="hf-cal__form hfval__form">\n <div class="hf-cal__form-submit hf-cal__form-submit--calendar">\n <button class="hf-cal__back hfval__back">Back</button>\n <button type="submit" class="hf-cal__form-button hf-cal__form-button--inline">Next</button>\n </div>\n </form>\n </div>\n\n </div>\n </div>\n\n </div>\n</div>\n<!-- end calendar page -->\n'; 12508 12509} 12510return __p 12511}})(); 12512(function() { 12513window["JST"] = window["JST"] || {}; 12514 12515window["JST"]["val_step4.html"] = function(obj) { 12516obj || (obj = {}); 12517var __t, __p = '', __j = Array.prototype.join; 12518function print() { __p += __j.call(arguments, '') } 12519with (obj) { 12520__p += '<div class="hf-cal__page hf-cal__step-4">\n <h2 class="hf-cal__page-title hf-cal__flex-pad">Request a valuation</h2>\n <div class="hf-cal__form-section">\n\n <form class="hf-cal__form hf-cal__form__flex hfval__form">\n '; 12521 if (uses_salutation) { ; 12522__p += '\n <div class="hf-cal_salutation">\n <div class="hf-cal__form-label">\n Title*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text hf-cal__form-element--title">\n <select\n id="hf-cal__valstep4__title"\n class="hf-cal__form-input hf-cal__form-input--text hf-cal__form-input--sal"\n type="text"\n name="title-name_param"\n data-hfbooking="title"\n autofocus\n required\n >\n <option value="Mr">Mr</option>\n <option value="Sir">Sir</option>\n <option value="Mrs">Mrs</option>\n <option value="Miss">Miss</option>\n <option value="Ms">Ms</option>\n <option value="Dr">Dr</option>\n <option value="Prof">Prof</option>\n </select>\n </div>\n </div>\n '; 12523 } ; 12524__p += '\n\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n First Name*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__valstep4__first-name"\n class="hf-cal__form-input hf-cal__form-input--text required"\n type="text"\n name="first-name_param"\n maxlength="25"\n data-hfbooking="first-name"\n '; 12525 if (userType == "persisted") { ; 12526__p += '\n value="' + 12527((__t = ( firstName )) == null ? '' : __t) + 12528'"\n readonly = true\n '; 12529 } ; 12530__p += '\n autofocus\n required\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Surname*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__valstep4__surname"\n class="hf-cal__form-input hf-cal__form-input--text required"\n type="text"\n name="surname_param"\n maxlength="25"\n data-hfbooking="last-name"\n '; 12531 if (userType == "persisted") { ; 12532__p += '\n value="' + 12533((__t = ( lastName )) == null ? '' : __t) + 12534'"\n readonly = true\n '; 12535 } ; 12536__p += '\n required\n />\n </div>\n </div>\n <!-- address section -->\n <div class="hf-cal__form__flex">\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n House Name\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__valstep4__house-name"\n class="hf-cal__form-input hf-cal__form-input--text"\n type="text"\n name="house-name_param"\n data-hfaddress="building-name"\n value="' + 12537((__t = ( buildingName )) == null ? '' : __t) + 12538'"\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n House Number\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__valstep4__house-number"\n class="hf-cal__form-input hf-cal__form-input--text"\n type="text"\n name="house-number_param"\n data-hfaddress="building-reference"\n value="' + 12539((__t = ( buildingNumber )) == null ? '' : __t) + 12540'"\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Street*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__valstep4__street"\n class="hf-cal__form-input hf-cal__form-input--text required"\n type="text"\n name="street_param"\n data-hfaddress="street"\n value="' + 12541((__t = ( street )) == null ? '' : __t) + 12542'"\n required\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Locality\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text hf-cal__form-element--text">\n <input\n id="hf-cal__valstep4__locality"\n class="hf-cal__form-input hf-cal__form-input--text"\n type="text"\n name="locality_param"\n data-hfaddress="locality-name"\n value="' + 12543((__t = ( locality )) == null ? '' : __t) + 12544'"\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n Town*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__valstep4__town"\n class="hf-cal__form-input hf-cal__form-input--text required"\n type="text"\n name="town_param"\n data-hfaddress="city"\n value="' + 12545((__t = ( town )) == null ? '' : __t) + 12546'"\n required\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group">\n <div class="hf-cal__form-label">\n County\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__valstep4__county"\n class="hf-cal__form-input hf-cal__form-input--text"\n type="text"\n name="county_param"\n data-hfaddress="province-name"\n value="' + 12547((__t = ( county )) == null ? '' : __t) + 12548'"\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group__postcode">\n <div class="hf-cal__form-label">\n Postcode*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text c
12548alendar-postcode">\n <input\n id="hf-cal__valstep4__postcode"\n class="hf-cal__form-input hf-cal__form-input--text required"\n type="text"\n name="postcode_param"\n data-hfaddress="postcode"\n pattern="^[a-zA-Z]{1,2}\\d[a-z\\d]?\\s*\\d[a-zA-Z]{2}$"\n value="' + 12549((__t = ( postcode )) == null ? '' : __t) + 12550'"\n required\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group_phone">\n <div class="hf-cal__form-label">\n Telephone*\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__valstep4__telephone"\n class="hf-cal__form-input hf-cal__form-input--text"\n type="tel"\n name="telephone_param"\n data-hfbooking="phone"\n value="' + 12551((__t = ( phone )) == null ? '' : __t) + 12552'"\n required\n pattern="^[+]?[0-9]{9,12}$"\n />\n </div>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group_phone">\n <div class="hf-cal__form-label">\n Mobile\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--text">\n <input\n id="hf-cal__valstep4__mobile"\n class="hf-cal__form-input hf-cal__form-input--text"\n type="mobile"\n name="mobile_param"\n data-hfbooking="mobile"\n value="' + 12553((__t = ( mobile )) == null ? '' : __t) + 12554'"\n pattern="^[+]?[0-9]{9,12}$"\n />\n </div>\n </div>\n <div class="hf-cal__form-group hf-cal__form-group_contact_message">\n <p class="tel_or_mobile">*Please enter a Telephone or Mobile number</p>\n </div>\n </div> <!-- end address section -->\n\n <div class="hf-cal__form-group hf-cal__form-group__full-width" style="margin-top: 22px;">\n <div class="hf-cal__form-label">\n ' + 12555((__t = ( propertyDescriptionText )) == null ? '' : __t) + 12556'\n </div>\n <textarea\n id="hf-cal__valstep4__details"\n class="hf-cal__form-input hf-cal__form-input--text"\n name="details_param"\n data-hfbooking="notes"\n >' + 12557((__t = ( notes )) == null ? '' : __t) + 12558'</textarea>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group__full-width">\n <div class="hf-cal__form-label">\n Are you also looking to:\n </div>\n <div class="hf-cal__form-element hf-cal__form-element--radio-group">\n <input\n id="hf-cal__valstep4__intention--buy"\n class="hf-cal__radio-input hfval__intention"\n value="buy"\n type="radio"\n name="intention"\n '; 12559 if (intention == 'buy') { ; 12560__p += '\n checked="checked"\n '; 12561 } ; 12562__p += '\n >\n <label for="hf-cal__valstep4__intention--buy" class="hf-cal__radio-label hf-cal__radio-option">Buy</label>\n <input\n id="hf-cal__valstep4__intention--rent"\n class="hf-cal__radio-input hfval__intention"\n value="rent"\n type="radio"\n name="intention"\n '; 12563 if (intention == 'rent') { ; 12564__p += '\n checked="checked"\n '; 12565 } ; 12566__p += '\n >\n <label for="hf-cal__valstep4__intention--rent" class="hf-cal__radio-label hf-cal__radio-option">Rent</label>\n <input\n id="hf-cal__valstep4__intention--neither"\n class="hf-cal__radio-input hfval__intention"\n value="neither"\n type="radio"\n name="intention"\n '; 12567 if (intention == 'neither') { ; 12568__p += '\n checked="checked"\n '; 12569 } ; 12570__p += '\n >\n <label for="hf-cal__valstep4__intention--neither" class="hf-cal__radio-label hf-cal__radio-option">Neither</label>\n </div>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group__opt-in hf-cal__form-group__full-width">\n <div class="hf-cal__form-element hf-cal__form-element--radio-group">\n <input\n id="hf-cal__valstep4__optin"\n class="hf-cal__radio-input"\n value="
125700"\n type="checkbox"\n name="mailOptIn"\n data-hfbooking="mail-optin"\n >\n <span onclick="" id="hf-cal__valstep4__optin_label" class="hf-cal__radio-label">Opt in for marketing communications. View <a class="hf-cal__link" target="_blank" href="/pages/terms-of-use">Terms & Conditions</a> and <a class="hf-cal__link" target="_blank" href="/pages/privacy-policy">\n Privacy Policy</a>. </span>\n </div>\n </div>\n\n <div class="hf-cal__form-group hf-cal__form-group__opt-in hf-cal__form-group__full-width">\n <div class="hf-cal__form-element hf-cal__form-element--radio-group">\n <input\n id="hf-cal__valstep4__tandcs"\n class="hf-cal__radio-input"\n value="0"\n type="checkbox"\n name="termsAndConditions"\n data-hfbooking="terms_and_conditions"\n required\n >\n <span onclick="" id="hf-cal__valstep4__tandcs_label" class="hf-cal__radio-label">I have read and agree to the Terms and Conditions, Privacy Policy and Cookies Policy*</span>\n </div>\n </div>\n\n <input\n hidden\n id="hf-cal__valstep4__optin_statement"\n name="optInStatement"\n value=""\n data-hfbooking="optin_statement"\n >\n <div class="hf-cal__form-submit hf-cal__form-group__full-width hf-cal__flex-pad">\n <button class="hf-cal__back hfval__back">Back</button>\n <button type="submit" class="hf-cal__form-button">Request</button>\n </div>\n </form>\n </div> <!-- end hf-cal__form-section -->\n</div>\n'; 12571 12572} 12573return __p 12574}})(); 12575(function() { 12576window["JST"] = window["JST"] || {}; 12577 12578window["JST"]["val_step5.html"] = function(obj) { 12579obj || (obj = {}); 12580var __t, __p = '', __j = Array.prototype.join; 12581function print() { __p += __j.call(arguments, '') } 12582with (obj) { 12583__p += '<div class="hf-cal__page hf-cal__step-5 hf-cal__flex-fill">\n\n '; 12584 if (error) { ; 12585__p += '\n <h2 class="hf-cal__page-title ">Sorry, something went wrong.</h2>\n <div class="hf-cal__text-section">\n <p>Please contact the ' + 12586((__t = ( office.name )) == null ? '' : __t) + 12587' branch on <a href="tel:' + 12588((__t = ( office.phonehref )) == null ? '' : __t) + 12589'">' + 12590((__t = ( office.phone )) == null ? '' : __t) + 12591'</a> or email <a href="maito:' + 12592((__t = ( office.email )) == null ? '' : __t) + 12593'">' + 12594((__t = ( office.email )) == null ? '' : __t) + 12595'</a> to arrange a valuation.</p>\n </div>\n '; 12596 } else if (justContactMe) { ; 12597__p += '\n <h2 class="hf-cal__page-title ">Thank you</h2>\n <div class="hf-cal__text-section">\n <p>Your valuation request has been received. We\'ll be in touch shortly.</p>\n </div>\n '; 12598 } else { ; 12599__p += '\n <h2 class="hf-cal__page-title ">Appointment Requested</h2>\n <div class="hf-cal__text-section">\n <p>Your valuation for ' + 12600((__t = ( address )) == null ? '' : __t) + 12601' has been requested for ' + 12602((__t = ( selectedTime.day )) == null ? '' : __t) + 12603'/' + 12604((__t = ( selectedTime.month + 1 )) == null ? '' : __t) + 12605'/' + 12606((__t = ( selectedTime.year )) == null ? '' : __t) + 12607' at ' + 12608((__t = ( ('0' + selectedTime.hours).slice(-2) )) == null ? '' : __t) + 12609':' + 12610((__t = ( ('0' + selectedTime.minutes).slice(-2) )) == null ? '' : __t) + 12611'.</p>\n\n <p >If you have any queries or need to cancel or amend your appointment, please call the ' + 12612((__t = ( office.name )) == null ? '' : __t) + 12613' branch on <a href="tel:' + 12614((__t = ( office.phonehref )) == null ? '' : __t) + 12615'">' + 12616((__t = ( office.phone )) == null ? '' : __t) + 12617'</a> or email <a href="maito:' + 12618((__t = ( office.email )) == null ? '' : __t) + 12619'">' + 12620((__t = ( office.email )) == null ? '' : __t) + 12621'</a> </p>\n </div>\n '; 12622 } ; 12623__p += '\n\n <div class="hf-cal__form-submit ">\n <button class="hf-cal__form-button" id="hfval__done-btn">Done</button>\n </div>\n\n</div>\n'; 12624 12625} 12626return __p 12627}})(); 12628HFBooking.ValStep = function(stepNumber) { 12629 this.stepNumber = stepNumber; 12630}; 12631 12632HFBooking.ValStep.prototype._getTemplate = function() { 12633 return JST['val_step' + this.stepNumber + '.html']; 12634} 12635 12636HFBooking.ValStep.prototype._addStepNumberClass = function() { 12637 $('#hfval__bg').removeClass (function (index, className) { 12638 return (className.match (/(^|\s)hfval__page-\S+/g) || []).join(' '); 12639 }).addClass('hfval__page-' + (this.stepNumber)); 12640} 12641 12642HFBooking.ValStep.prototype.render = function() { 12643 var stepTemplate = this._getTemplate(); 12644 this._addStepNumberClass(); 12645 12646 switch (this.stepNumber) { 12647 case 1:
12648 if (Ctesius.getUser() && Ctesius.getUser().get('email')) { 12649 var email = Ctesius.getUser().attributes.email 12650 } else if (HFBooking.Valuation.payload.email) { 12651 var email = HFBooking.Valuation.payload.email 12652 } else { 12653 var email = "" 12654 } 12655 $('#hfval__content').html(stepTemplate({ 12656 postcode: HFBooking.Valuation.payload.postcode_param, 12657 channel: HFBooking.Valuation.payload.channel, 12658 email: email 12659 })); 12660 break; 12661 case 2: 12662 $('#hfval__content').html(stepTemplate({ 12663 addresses: HFBooking.Valuation.addresses, 12664 rawAddresses: HFBooking.Valuation.rawAddresses, 12665 })); 12666 break; 12667 case 3: 12668 $('#hfval__content').html(stepTemplate({ 12669 hfOnlyCal: HFBooking.Valuation.payload.hfOnlyCal, 12670 wcDate: HFBooking.Valuation.wcDate, 12671 days: HFBooking.Valuation.calendarData.days, 12672 monthData: HFBooking.Valuation.calendarData.monthData, 12673 currentMonth: HFBooking.Valuation.calendarData.currentMonth, 12674 branchId: HFBooking.Valuation.branchId, 12675 selectedTimeslot: HFBooking.Valuation.selectedTimeslot, 12676 selectedWeek: HFBooking.Valuation.selectedWeek, 12677 currentDay: HFBooking.Process.getCurrentDay(), 12678 nextDay: HFBooking.Process.getNextDay(), 12679 currentTime: HFBooking.Process.getCurrentTime(), 12680 bufferTime: HFBooking.Process.bufferTime(), 12681 bufferDay: HFBooking.Process.bufferDay(), 12682 buffer: HFBooking.Process.bufferClockTime() 12683 })); 12684 if (HFBooking.Valuation.error){ 12685 HFBooking.Process.deselectChosenDate(); 12686 HFBooking.Process.displayAlert(HFBooking.Valuation.errorMessage, 'error'); 12687 } 12688 break; 12689 case 4: 12690 if (HFBooking.Valuation.payload.address) { 12691 var splitAddress = HFBooking.Valuation.payload.address.split(','); 12692 if (/\d/.test(splitAddress[1])) { // if the second part contains a number 12693 var buildingName = splitAddress[0] 12694 var buildingNumber = splitAddress[1].trim().split(' ')[0]; 12695 var street = splitAddress[1].trim().split(' ').splice(1).join(' '); 12696 } else { 12697 var buildingNumber = splitAddress[0].split(' ')[0]; 12698 var street = splitAddress[0].split(' ').slice(1).join(' '); 12699 } 12700 var town = splitAddress[5].trim(); 12701 var county = splitAddress[6].trim(); 12702 } 12703 var user = Ctesius.getUser(); 12704 $('#hfval__content').html(stepTemplate({ 12705 uses_salutation: Ctesius.getConfig('uses_RDA_salutation'), 12706 userType: user.userType(), 12707 buildingName: HFBooking.Valuation.formattedBuildingName, 12708 buildingNumber: HFBooking.Valuation.formattedBuildingNumber, 12709 street: HFBooking.Valuation.formattedStreet, 12710 town: HFBooking.Valuation.formattedTown, 12711 county: HFBooking.Valuation.formattedCounty, 12712 locality: HFBooking.Valuation.formattedLocality, 12713 postcode: HFBooking.Valuation.payload.postcode_param, 12714 firstName: user.attributes.first_name, 12715 lastName: user.attributes.last_name, 12716 phone: user.attributes.tel_home, 12717 mobile: user.attributes.tel_mobile, 12718 channel: HFBooking.Valuation.payload.channel, 12719 intention: HFBooking.Valuation.payload.intention, 12720 notes: HFBooking.Valuation.payload.notes, 12721 propertyDescriptionText: HFBooking.Process.propertyDescriptionText() 12722 })); 12723 break; 12724 case 5: 12725 if (HFBooking.Valuation.payload.branch) { 12726 var default_office = HFBooking.Valuation.payload.branch.branch 12727 } 12728 $('#hfval__content').html(stepTemplate({ 12729 justContactMe: HFBooking.Valuation.payload.justContactMe, 12730 address: HFBooking.Valuation.payload.finalAddress, 12731 selectedTime: HFBooking.Valuation.selectedTimeslot, 12732 default_office: default_office, 12733 office: HFBooking.Process.getValuationOffice(HFBooking.Valuation.office), 12734 error: HFBooking.Valuation.error, 12735 customMessage: HFBooking.Process.getCustomValuationMessage(), 12736 })); 12737 break; 12738 default: 12739 $('#hfval__content').html(stepTemplate()); 12740 break; 12741 } 12742} 12743 12744HFBooking.ValStep.prototype.calendarValidation = function() {
12745 var valid = true 12746 var validNames = true 12747 var phoneInputValid; 12748 var allInputs = document.querySelectorAll('.hf-cal__form .required'); 12749 12750 var phone = document.querySelector('.hf-cal__form #hf-cal__valstep4__telephone'); 12751 var mobile = document.querySelector('.hf-cal__form #hf-cal__valstep4__mobile'); 12752 var phoneValid = /^[+]*[0-9\s]{6,14}$/.test(phone.value); 12753 var mobileValid = /^[+]*[0-9\s]{6,14}$/.test(mobile.value); 12754 var phonePresent = phone.value != '' 12755 var mobilePresent = mobile.value != '' 12756 var tel_and_mobile = document.querySelectorAll('.hf-cal__form #hf-cal__valstep4__telephone, #hf-cal__valstep4__mobile'); 12757 var firstNameInput = $('.hf-cal__form #hf-cal__valstep4__first-name').val().toLowerCase().replace(/\s/g,'') 12758 var lastNameInput = $('.hf-cal__form #hf-cal__valstep4__surname').val().toLowerCase().replace(/\s/g,'') 12759 12760 var postcode = document.querySelector('.hf-cal__form #hf-cal__valstep4__postcode'); 12761 var postcode_valid = /^([A-Za-z][A-Ha-hJ-Yj-y]?[0-9][A-Za-z0-9]? ?[0-9][A-Za-z]{2}|[Gg][Ii][Rr] ?0[Aa]{2})$/.test(postcode.value); 12762 12763 var termsInput = document.querySelector('#hf-cal__valstep4__tandcs'); 12764 var input_valid = document.querySelector('#hf-cal__valstep4__tandcs_label'); 12765 12766 for (var i=0; i<allInputs.length; i++){ 12767 if (allInputs[i].value == ''){ 12768 allInputs[i].classList.add('validate'); 12769 valid = false; 12770 } 12771 } 12772 12773 if(firstNameInput === lastNameInput) { 12774 validNames = false; 12775 } 12776 12777 if ((phonePresent && phoneValid) || (mobilePresent && mobileValid)) { 12778 phoneInputValid = true; 12779 } 12780 12781 if (!phoneInputValid) { 12782 phoneInputValid = false; 12783 if (!phonePresent && !mobilePresent) { 12784 phone.classList.add('validate'); 12785 mobile.classList.add('validate'); 12786 } else if (phonePresent && !phoneValid) { 12787 phone.classList.add('validate'); 12788 } else if (mobilePresent && !mobileValid) { 12789 mobile.classList.add('validate'); 12790 } 12791 } 12792 12793 if(postcode.value == '' || postcode_valid == false){ 12794 postcode.classList.add('validate'); 12795 valid = false; 12796 } 12797 12798 if(termsInput.value == '0'){ 12799 input_valid.classList.add('terms_failed'); 12800 valid = false; 12801 } 12802 12803 var failedInputs = document.querySelectorAll('.hf-cal__form .validate'); 12804 12805 function removeClass(){ 12806 if(phone.classList.contains('validate')){ 12807 phone.classList.remove('validate'); 12808 } 12809 if(mobile.classList.contains('validate')){ 12810 mobile.classList.remove('validate'); 12811 } 12812 } 12813 12814 for(i=0; i<failedInputs.length; i++){ 12815 failedInputs[i].addEventListener('keyup', function(){ 12816 this.classList.remove('validate'); 12817 }); 12818 failedInputs[i].addEventListener('click', function(){ 12819 this.classList.remove('validate'); 12820 }); 12821 } 12822 12823 for(var i=0; i<tel_and_mobile.length; i++){ 12824 tel_and_mobile[i].addEventListener('keyup', function(){ 12825 removeClass(); 12826 }); 12827 tel_and_mobile[i].addEventListener('click', function(){ 12828 removeClass(); 12829 }); 12830 } 12831 12832 window.addEventListener('change', phones); 12833 window.addEventListener('change', inputs); 12834 input_valid.addEventListener('click', terms); 12835 12836 function phones(){ 12837 for(var i=0; i<tel_and_mobile.length; i++){ 12838 if(tel_and_mobile[i].value != ''){ 12839 if(phone.classList.contains('validate')){ 12840 phone.classList.remove('validate'); 12841 } 12842 if(mobile.classList.contains('validate')){ 12843 mobile.classList.remove('validate'); 12844 } 12845 } 12846 } 12847 } 12848 12849 function inputs(){ 12850 for (var i=0; i<failedInputs.length; i++){ 12851 if(failedInputs[i].value != ''){ 12852 failedInputs[i].classList.remove('validate'); 12853 } 12854 } 12855 } 12856 12857 function terms(){ 12858 if(input_valid.classList.contains('terms_failed')){ 12859 input_valid.classList.remove('terms_failed'); 12860 valid = true; 12861 } 12862 } 12863 12864 if (valid && validNames && phoneInputValid) { 12865 return { passed: true, failMessage: null }; 12866 } else if (valid && !validNames) { 12867 return { passed: false, failMessage: 'First name and Surname must not be the same' }; 12868 } else if (valid && !phoneInputValid) { 12869 return { passed: false, failMessage: 'Phone numbers must be longer than 6 digits' }; 12870 } else {
12871 return { passed: false, failMessage: 'Please fill in all required fields' }; 12872 } 12873} 12874 12875HFBooking.ValStep.prototype.validate = function() { 12876 // validate form fields for the given step 12877 switch (this.stepNumber) { 12878 case 3: 12879 if (!HFBooking.Valuation.payload.chosenTime && !HFBooking.Valuation.payload.justContactMe) { 12880 alert('Please select a time slot.'); 12881 return false; 12882 } else { 12883 return true; 12884 } 12885 default: 12886 return true; 12887 } 12888} 12889 12890HFBooking.ViewStep = function(stepNumber) { 12891 this.stepNumber = stepNumber; 12892}; 12893 12894HFBooking.ViewStep.prototype._getTemplate = function() { 12895 return JST['view_step' + this.stepNumber + '.html']; 12896} 12897 12898HFBooking.ViewStep.prototype._addStepNumberClass = function() { 12899 $('#hfview__bg').removeClass (function (index, className) { 12900 return (className.match (/(^|\s)hfview__page-\S+/g) || []).join(' '); 12901 }).addClass('hfview__page-' + (this.stepNumber)); 12902} 12903 12904HFBooking.ViewStep.prototype.render = function() { 12905 var stepTemplate = this._getTemplate(); 12906 this._addStepNumberClass(); 12907 12908 switch (this.stepNumber) { 12909 case 1: 12910 var user = Ctesius.getUser().attributes; 12911 var altCtaText = Ctesius.getConfig('alt_cta_viewing_form'); 12912 var altButtonText = Ctesius.getConfig('alt_button_viewing_form'); 12913 12914 function getCtaText() { 12915 return altCtaText ? altCtaText : 'Book a viewing' 12916 } 12917 12918 function getButtonText() { 12919 return altButtonText ? altButtonText : 'View appointments'; 12920 }; 12921 12922 $('#hfview__content').html(stepTemplate({ 12923 property: HFBooking.Viewing.property, 12924 email: user.email, 12925 ctaText: getCtaText(), 12926 buttonText: getButtonText() 12927 })); 12928 break; 12929 case 2: 12930 12931 var altIntroText = Ctesius.getConfig('alt_intro_viewing_form'); 12932 12933 function getIntroText() { 12934 return altIntroText ? altIntroText : 'Please choose a date and time you would like your viewing. If your desired time is not available then click the button below and we will get in touch'; 12935 } 12936 12937 $('#hfview__content').html(stepTemplate({ 12938 hfOnlyCal: HFBooking.Viewing.payload.hfOnlyCal, 12939 wcDate: HFBooking.Viewing.wcDate, 12940 days: HFBooking.Viewing.calendarData.days, 12941 monthData: HFBooking.Viewing.calendarData.monthData, 12942 currentMonth: HFBooking.Viewing.calendarData.currentMonth, 12943 branchId: HFBooking.Viewing.branchId, 12944 selectedTimeslot: HFBooking.Viewing.selectedTimeslot, 12945 selectedWeek: HFBooking.Viewing.selectedWeek, 12946 todayDayDate: HFBooking.Process.getTodayDayDate(), 12947 currentDay: HFBooking.Process.getCurrentDay(), 12948 nextDay: HFBooking.Process.getNextDay(), 12949 currentTime: HFBooking.Process.getCurrentTime(), 12950 bufferTime: HFBooking.Process.bufferTime(), 12951 bufferDay: HFBooking.Process.bufferDay(), 12952 buffer: HFBooking.Process.bufferClockTime(), 12953 introText: getIntroText() 12954 })); 12955 if (HFBooking.Viewing.error){ 12956 HFBooking.Process.deselectChosenDate(); 12957 HFBooking.Process.displayAlert(HFBooking.Viewing.errorMessage, 'error'); 12958 } 12959 break; 12960 case 3: 12961 var user = Ctesius.getUser().attributes; 12962 $('#hfview__content').html(stepTemplate({ 12963 uses_salutation: Ctesius.getConfig('uses_RDA_salutation'), 12964 userType: Ctesius.getUser().userType(), 12965 userEmail: HFBooking.Viewing.payload.email, 12966 firstName: user.first_name, 12967 lastName: user.last_name, 12968 phone: user.tel_home, 12969 mobile: user.tel_mobile, 12970 house_name: user.house_name, 12971 house_number: user.house_number, 12972 street: user.street_address, 12973 locality: user.locality, 12974 town: user.town, 12975 county: user.county, 12976 postcode: user.postcode, 12977 notes: HFBooking.Viewing.payload.notes, 12978 })); 12979 break; 12980 case 4: 12981 $('#hfview__content').html(stepTemplate({ 12982 justContactMe: HFBooking.Viewing.payload.justContactMe, 12983 property: HFBooking.Viewing.property, 12984 selectedTime: HFBooking.Viewing.selectedTimeslot, 12985 office: HFBooking.Process.getViewingOffice(HFBooking.Viewing.office), 12986 error: HFBooking.Viewing.error, 12987 justContactMe: HFBooking.Viewing.payload.justContactMe, 12988 })); 12989 break; 12990 default: 12991 $('#hfview__content').html(stepTemplate()); 12992 break; 12993 } 12994} 12995 12996HFBooking.ViewStep.prototype.calendarValidation = function() {
12997 var valid = true 12998 var validNames = true 12999 var phoneInputValid; 13000 var allInputs = document.querySelectorAll('.hf-cal__form .required'); 13001 13002 var phone = document.querySelector('.hf-cal__form #hf-cal__viewstep3__telephone'); 13003 var mobile = document.querySelector('.hf-cal__form #hf-cal__viewstep3__mobile'); 13004 var phonePresent = phone.value != '' 13005 var mobilePresent = mobile.value != '' 13006 var phoneValid = /^[+]*[0-9\s]{6,14}$/.test(phone.value); 13007 var mobileValid = /^[+]*[0-9\s]{6,14}$/.test(mobile.value); 13008 var tel_and_mobile = document.querySelectorAll('.hf-cal__form #hf-cal__viewstep3__telephone, #hf-cal__viewstep3__mobile'); 13009 var firstNameInput = $('.hf-cal__form #hf-cal__viewstep3__first-name').val().toLowerCase().replace(/\s/g,'') 13010 var lastNameInput = $('.hf-cal__form #hf-cal__viewstep3__surname').val().toLowerCase().replace(/\s/g,'') 13011 13012 var email = document.querySelector('.hf-cal__form #hf-cal__viewstep3__email-address'); 13013 var email_valid = /^([\w.-]+)@([\w.-]+)\.([a-zA-Z.]{2,6})$/i.test(email.value); 13014 13015 var postcode = document.querySelector('.hf-cal__form #hf-cal__viewstep3__postcode'); 13016 var postcode_valid = /^([A-Za-z][A-Ha-hJ-Yj-y]?[0-9][A-Za-z0-9]? ?[0-9][A-Za-z]{2}|[Gg][Ii][Rr] ?0[Aa]{2})$/.test(postcode.value); 13017 13018 var termsInput = document.querySelector('#hf-cal__viewstep3__tandcs'); 13019 var input_valid = document.querySelector('#hf-cal__viewstep3__tandcs_label'); 13020 13021 for (var i=0; i<allInputs.length; i++){ 13022 if (allInputs[i].value == ''){ 13023 allInputs[i].classList.add('validate'); 13024 valid = false; 13025 } 13026 } 13027 13028 if(firstNameInput === lastNameInput) { 13029 validNames = false; 13030 } 13031 13032 if ((phonePresent && phoneValid) || (mobilePresent && mobileValid)) { 13033 phoneInputValid = true; 13034 } 13035 13036 if (!phoneInputValid) { 13037 phoneInputValid = false; 13038 if (!phonePresent && !mobilePresent) { 13039 phone.classList.add('validate'); 13040 mobile.classList.add('validate'); 13041 } else if (phonePresent && !phoneValid) { 13042 phone.classList.add('validate'); 13043 } else if (mobilePresent && !mobileValid) { 13044 mobile.classList.add('validate'); 13045 } 13046 } 13047 13048 if(email.value == '' || email_valid == false){ 13049 email.classList.add('validate'); 13050 valid = false; 13051 } 13052 13053 if(postcode.value == '' || postcode_valid == false){ 13054 postcode.classList.add('validate'); 13055 valid = false; 13056 } 13057 13058 if(termsInput.value == '0'){ 13059 input_valid.classList.add('terms_failed'); 13060 valid = false; 13061 } 13062 13063 var failedInputs = document.querySelectorAll('.hf-cal__form .validate'); 13064 13065 for(var i=0; i<tel_and_mobile.length; i++){ 13066 tel_and_mobile[i].addEventListener('click', function(){ 13067 if(phone.classList.contains('validate')){ 13068 phone.classList.remove('validate'); 13069 } 13070 if(mobile.classList.contains('validate')){ 13071 mobile.classList.remove('validate'); 13072 } 13073 }) 13074 } 13075 13076 for(i=0; i<failedInputs.length; i++){ 13077 failedInputs[i].addEventListener('click', function(){ 13078 this.classList.remove('validate'); 13079 }); 13080 } 13081 13082 window.addEventListener('change', phones); 13083 window.addEventListener('change', inputs); 13084 input_valid.addEventListener('click', terms); 13085 13086 function phones(){ 13087 for(var i=0; i<tel_and_mobile.length; i++){ 13088 if(tel_and_mobile[i].value != ''){ 13089 if(phone.classList.contains('validate')){ 13090 phone.classList.remove('validate'); 13091 } 13092 if(mobile.classList.contains('validate')){ 13093 mobile.classList.remove('validate'); 13094 } 13095 } 13096 } 13097 } 13098 13099 function inputs(){ 13100 for (var i=0; i<failedInputs.length; i++){ 13101 if(failedInputs[i].value != ''){ 13102 failedInputs[i].classList.remove('validate'); 13103 } 13104 } 13105 } 13106 13107 function terms(){ 13108 if(input_valid.classList.contains('terms_failed')){ 13109 input_valid.classList.remove('terms_failed'); 13110 valid = true; 13111 } 13112 } 13113 13114 if (valid && validNames && phoneInputValid) { 13115 return { passed: true, failMessage: null }; 13116 } else if (valid && !validNames) { 13117 return { passed: false, failMessage: 'First name and Surname must not be the same' }; 13118 } else if (valid && !phoneInputValid) { 13119 return { passed: false, failMessage: 'Phone numbers must be longer than 6 digits' }; 13120 } else {
13121 return { passed: false, failMessage: 'Please fill in all required fields' }; 13122 } 13123} 13124 13125HFBooking.ViewStep.prototype.validate = function() { 13126 switch (this.stepNumber) { 13127 case 1: 13128 var email = $('#hf-cal__viewstep1__email-address').val(); 13129 var email_valid = /^([\w.-]+)@([\w.-]+)\.([a-zA-Z.]{2,6})$/i.test(email); 13130 if (!email_valid) { 13131 alert('Please enter a valid email address.'); 13132 return false; 13133 break; 13134 } 13135 return true; 13136 break; 13137 case 2: 13138 if (!HFBooking.Viewing.payload.chosenTime && !HFBooking.Viewing.payload.justContactMe) { 13139 alert('Please select a time slot.'); 13140 return false; 13141 } else { 13142 return true; 13143 } 13144 case 3: 13145 var finalValidation = this.calendarValidation(); 13146 if (!finalValidation.passed) { 13147 alert(finalValidation.failMessage); 13148 return false; 13149 } 13150 default: 13151 return true; 13152 } 13153} 13154 13155HFBooking.Valuation = Object.create(HFBooking.Process, { 13156 step1: { value: new HFBooking.ValStep(1) }, 13157 step2: { value: new HFBooking.ValStep(2) }, 13158 step3: { value: new HFBooking.ValStep(3) }, 13159 step4: { value: new HFBooking.ValStep(4) }, 13160 step5: { value: new HFBooking.ValStep(5) }, 13161 13162 events: { 13163 value: { 13164 'click .hfval__open': 'openModal', 13165 'click .hf-cal__close': 'closeModal', 13166 'click .hfval__back': 'previousStep', 13167 'click #hfval__nextmonth': 'nextMonth', 13168 'click #hfval__prevmonth': 'prevMonth', 13169 'click #hfval__nextweek': 'nextWeek', 13170 'click #hfval__prevweek': 'prevWeek', 13171 'click #hfval__nextday': 'nextDay', 13172 'click #hfval__prevday': 'prevDay', 13173 'click .hfval__month--day': 'selectWeek', 13174 'click .hfval__timeslot': 'selectTimeslot', 13175 'click #hfval__done-btn': 'done', 13176 'click #hfval__just-contact-me': 'justContactMe', 13177 'click #hf-cal__valstep4__optin_label': 'toggleMarketingOptionVal', 13178 'click #hf-cal__valstep4__tandcs_label': 'toggleTermsAndConditions', 13179 } 13180 }, 13181 13182 createModal: { 13183 value: function() { 13184 // build outer markup for the modal and append to the page: 13185 var $modalBg = $('<div id="hfval__bg" class="hf-cal inactive">'); 13186 var $window = $('<div class="hf-cal__window" style="z-index: 9999999999;">'); 13187 var $backdrop = $('<div class="hf-cal__backdrop">'); 13188 $window.append('<a href="#" class="hf-cal__close"><p>×</p></a>');
13189 var $container = $('<div class="hf-cal__container">'); 13190 $container.append('<div id="hfval__content" class="hf-cal__content">'); 13191 $($window).append($container); 13192 $($modalBg).append($window); 13193 $($modalBg).append($backdrop); 13194 $('body').append($modalBg); 13195 } 13196 }, 13197 13198 openModal: { 13199 value: function() { 13200 console.log('Opening modal...'); 13201 this.renderStep(1) 13202 $('#hfval__bg').removeClass('inactive'); 13203 } 13204 }, 13205 13206 closeModal: { 13207 value: function() { 13208 this.reset(); 13209 HFBooking.Valuation.currentStep = 1; 13210 $('#hfval__bg').addClass('inactive'); 13211 window.location.hash = ''; 13212 } 13213 }, 13214 13215 done: { 13216 value: function() { 13217 this.reset(); 13218 console.log('val done reset') 13219 this.closeModal(); 13220 } 13221 }, 13222 13223 reset: { 13224 value: function() { 13225 this.payload = { 13226 branchId: false, 13227 channel: '', 13228 addressData: {}, 13229 email: '', 13230 postcode_param: '', 13231 }; 13232 this.currentStep = 1; 13233 this.addresses = []; 13234 this.calendarData = { 13235 currentMonth: new Date().getMonth(), 13236 }; 13237 this.selectedWeek = false; 13238 this.selectedTimeslot = { 13239 day: false, 13240 hours: false, 13241 minutes: false, 13242 }; 13243 } 13244 }, 13245 13246 previousStep: { 13247 value: function(e) { 13248 e.preventDefault(); 13249 this.updatePayloadFromFields(); 13250 if (this.payload.justContactMe && this.currentStep === 4) { 13251 if (this.payload.address === undefined){ 13252 this.currentStep -= 3; 13253 }else { 13254 this.currentStep -= 2; 13255 } 13256 } else { 13257 this.currentStep--; 13258 } 13259 this['step' + this.currentStep].render(); 13260 } 13261 }, 13262 13263 nextStep: { 13264 value: function() { 13265 this.updatePayloadFromFields(); 13266 if (this['step' + this.currentStep].validate()) { 13267 switch (this.currentStep) { 13268 case 1: 13269 var postcode = $('#hf-cal__postcode').val(); 13270 this.getAddresses(postcode); 13271 this.currentStep++; 13272 break; 13273 case 2: 13274 this.currentStep++; 13275 this.formattedAddressFields(); 13276 break; 13277 case 4: 13278 this.currentStep++; 13279 this.payload.street_address = $('#hf-cal__valstep4__street').val(); 13280 this.sendPayload(); 13281 break; 13282 default: 13283 this.renderStep(this.currentStep + 1); 13284 this.currentStep++; 13285 break; 13286 } 13287 } else { 13288 $('.hf-cal__form-button').removeAttr('disabled'); 13289 console.log('failed validation'); 13290 } 13291 } 13292 }, 13293 13294 updatePayloadFromFields: { 13295 value: function() { 13296 var $fields = $('[data-hfbooking]'); 13297 for (var i=0; i<$fields.length; i++) { 13298 var $field = $($fields[i]); 13299 this.updatePayload($field.data('hfbooking'), $field.val()); 13300 } 13301 var $addressFields = $('[data-hfaddress]'); 13302 for (var i=0; i<$addressFields.length; i++) { 13303 var $field = $($addressFields[i]); 13304 this.updateAddress($field.data('hfaddress'), $field.val()); 13305 } 13306 } 13307 }, 13308 13309 formattedAddressFields: { 13310 value: function(){ 13311 if (HFBooking.Valuation.payload.address) { 13312 var splitAddress = HFBooking.Valuation.payload.address.split(',');
13313 var houseNumber = HFBooking.Valuation.findHouseNumber(splitAddress); 13314 var buildingName = HFBooking.Valuation.findBuildingName(splitAddress); 13315 var default_lookup_param = splitAddress[0] 13316 HFBooking.Valuation.getFormattedAddresses(HFBooking.Valuation.payload.postcode_param, houseNumber, buildingName, default_lookup_param); 13317 } 13318 } 13319 }, 13320 13321 findHouseNumber: { 13322 value: function(splitAddress) { 13323 var alphanumericStreetNumber = /^\d{1,4}(?:[a-zA-z-]{1,2}\d{0,3})*?$/; 13324 var trimmedAddresses = splitAddress.map(function(element){ return element.trim()}); 13325 var streetAddress = trimmedAddresses.filter(function(val, i, arr){ 13326 if(trimmedAddresses[i].split(' ').shift().match(alphanumericStreetNumber)){ 13327 return trimmedAddresses[i].split(' ').shift(); 13328 } 13329 }); 13330 if(streetAddress !== undefined && streetAddress.length !== 0){ 13331 var houseNumber = streetAddress[0].split(' ').shift(); 13332 return houseNumber; 13333 } 13334 } 13335 }, 13336 13337 findBuildingName: { 13338 value: function(splitAddress) { 13339 var values = ['flat','apartment'] 13340 for (var i = 0; i < values.length; i++) { 13341 var substring = values[i]; 13342 if (splitAddress[i].toLowerCase().indexOf(substring) >= 0) { 13343 return splitAddress[i]; 13344 } 13345 } 13346 } 13347 }, 13348 13349 getAddresses: { 13350 value: function(postcode) { 13351 var _this = this; 13352 $.getJSON('/address_lookup?postcode=' + postcode, function(data) { 13353 if (data.Message) { 13354 _this.payload.email = $('#hf-cal__email-address').val(); 13355 _this.payload.justContactMe = true; 13356 _this.currentStep = 4; 13357 _this.renderStep(4); 13358 } else { 13359 _this.populateAddresses(data); 13360 _this.rawAddresses = data.Addresses; 13361 _this.renderStep(2); 13362 } 13363 }) 13364 } 13365 }, 13366 13367 getFormattedAddresses: { 13368 value: function(postcode, houseNumber, buildingName, default_lookup_param) { 13369 var _this = this; 13370 var postcodeSearchValue = _this.postcodeSearchValue(houseNumber, buildingName, default_lookup_param); 13371 $.getJSON('/address_lookup?postcode=' + postcode + '&house_number=' + postcodeSearchValue + '&expand=true', function(data) { 13372 if (data.Message) { 13373 _this.payload.justContactMe = true; 13374 _this.currentStep = 4; 13375 _this.renderStep(4) 13376 } else { 13377 _this.formattedAddresses = data.addresses; 13378 _this.formattedAddressesParser(data.addresses, houseNumber, buildingName); 13379 _this.getDates(); 13380 } 13381 }) 13382 } 13383 }, 13384 13385 postcodeSearchValue: { 13386 value: function(houseNumber, buildingName, default_lookup_param){ 13387 if (houseNumber && buildingName) { 13388 return buildingName + ', ' + houseNumber 13389 } else if (houseNumber) { 13390 return houseNumber 13391 } else if (buildingName) { 13392 return buildingName 13393 } else { 13394 return default_lookup_param 13395 } 13396 } 13397 }, 13398 13399 formattedAddressesParser: { 13400 value: function(expandedAddress, houseNumber, buildingName){ 13401 var _this = this; 13402 if ((houseNumber !== undefined) && (buildingName !== undefined )) { 13403 var correctAddress = expandedAddress.filter(function(obj, i, arr){ 13404 if(arr[i].sub_building_name === buildingName){ 13405 return arr[i] 13406 }else if(arr[i].building_number === houseNumber){ 13407 return arr[i] 13408 } 13409 }) 13410 } else { 13411 var correctAddress = expandedAddress 13412 } 13413 _this.formattedAddress = correctAddress[0].formatted_address 13414 _this.formattedBuildingName = correctAddress[0].sub_building_name + ' ' + correctAddress[0].building_name; 13415 _this.formattedBuildingNumber = correctAddress[0].building_number; 13416 _this.formattedStreet = correctAddress[0].thoroughfare; 13417 _this.formattedTown = correctAddress[0].town_or_city; 13418 _this.formattedCounty = correctAddress[0].county; 13419 _this.formattedLocality = correctAddress[0].locality; 13420 } 13421 }, 13422 13423 getDates: { 13424 value: function() { 13425 console.log('Getting dates...'); 13426 13427 // show loading spinner 13428 $('.hf-cal__content').html('<div class="hfcal__loader"><div class="hfcal__loader-inner"></div></div>'); 13429
13430 if (!this.wcDate) { this.wcDate = this.getStartOfWeek(new Date()); } 13431 13432 wc = { 13433 y: this.wcDate.getFullYear(), 13434 m: this.wcDate.getMonth(), 13435 d: this.wcDate.getDate(), 13436 }; 13437 var requestData = { wc: wc, data: this.payload } 13438 var _this = this; 13439 // make AJAX request to get timeslots from Ctesius / Reapit: 13440 $.getJSON('/calendar_bookings', requestData, function(data) { 13441 _this.addBranchDetails(_this.payload, data) 13442 if (data.error) { 13443 console.log("Response: ", data.error); 13444 _this.payload.justContactMe = true; 13445 _this.currentStep++; 13446 _this.renderStep(4); 13447 } else { 13448 _this.payload.hfOnlyCal = data.hf_only_cal; 13449 _this.calendarData.days = data.days; 13450 // TODO: What if the week straddles 2 different years? data.days[0].y might be wrong one... 13451 _this.calendarData.monthData = _this.buildMonth(_this.calendarData.currentMonth, data.days.appointments[1].y); 13452 _this.payload.officeCode = data.office_code; //Reapit Agents only 13453 _this.currentStep = 3; 13454 _this.renderStep(3); 13455 } 13456 }); 13457 } 13458 }, 13459 13460 sendPayload: { 13461 value: function() { 13462 _this = this; 13463 // show loading spinner 13464 $('.hf-cal__content').html('<div class="hfcal__loader"><div class="hfcal__loader-inner"></div></div>'); 13465 $.ajax({ 13466 url: '/calendar_bookings', 13467 method: 'POST', 13468 data: this.payload, 13469 success: function(response) { 13470 if (response.error) { 13471 _this.handleError(response); 13472 } else { 13473 _this.office = HFBooking.Valuation.payload.branch; 13474 _this.payload.finalAddress = response.final_address; 13475 _this.error = false; 13476 Ctesius.kickEvent('calendar_booking_complete', _this.payload, 'Valuation'); 13477 _this.renderStep(5); 13478 } 13479 }, 13480 }) 13481 } 13482 }, 13483 13484 handleError: { 13485 value: function(response) { 13486 console.log("ERROR", response); 13487 _this.error = true; 13488 _this.office = HFBooking.Valuation.payload.branch; 13489 if (response.error === 'Negotiator unavailable at this time'){ 13490 var month = HFBooking.Valuation.selectedTimeslot.month + 1 13491 var date = HFBooking.Valuation.selectedTimeslot.day + '-' + month + '-' + HFBooking.Valuation.selectedTimeslot.year; 13492 var date_time = HFBooking.Valuation.payload.chosenTime + ' on ' + date; 13493 _this.errorMessage = 'Selected time of ' + date_time + ' is unavailable. Please choose a different time.'; 13494 _this.getDates(); 13495 }else{ 13496 _this.renderStep(5); 13497 } 13498 } 13499 } 13500}); 13501 13502// {:lead_client=> 13503// {:first_name=>"fkewm", 13504// :last_name=>"glkmrel", 13505// :email=>"[email protected]", 13506// :tel_home=>"0985739453", 13507// :do_not_contact=>false, 13508// :postcode=>"SE3 9LA", 13509// :street_address=>" 1 Blackheath Village"}, 13510// :lead=> 13511// {:branch_id=>"32975", 13512// :message=>"ewkj ewfkm lfew lkmfe lkmef.", 13513// :starting=>"2018-2-13T9:30", 13514// :ending=>"2018-2-13T10:0", 13515// :is_valuation_request=>"1", 13516// :client_booking_date_time=>Tue, 13 Feb 2018 09:30:00 +0000, 13517// :service_provider_name=>"Reapit Live", 13518// :is_branch_lead=>"1"}, 13519// :client=>{:valuation_reason=>"sales"}} 13520 13521 13522// GENERATE MONTH 13523// days is a week (first one will be current week) 13524// we need to figure out 13525 13526// branch ref example: rps_mns-ADE 13527 13528// Example of params coming from WW front-end to Ctesius for first request: 13529// {"wc"=>{"y"=>"2018", "m"=>"0", "d"=>"19"}, 13530// "data"=> 13531// {"email"=>"[email protected]", 13532// "type"=>"false", 13533// "firstName"=>"false", 13534// "lastName"=>"false", 13535// "phone"=>"false", 13536// "date"=>"false", 13537// "address_lat_lng"=>"[51.465613,0.009469]", 13538// "street_address"=>"3A, Blackheath Village", 13539// "town"=>"London", 13540// "county"=>"", 13541// "postcode_param"=>"SE3 9LA", 13542// "intention"=>"false", 13543// "address"=>"3A Blackheath Village\nLONDON\nSE3 9LA\nUNITED KINGDOM", 13544// "addressData"=> 13545// {"Id"=>"GB|RM|A|52046636", 13546// "DomesticId"=>"52046636", 13547// "Language"=>"ENG", 13548// "LanguageAlternatives"=>"ENG", 13549// "Department"=>"", 13550// "Company"=>"", 13551// "SubBuilding"=>"", 13552// "buildingName"=>"", 13553// "BuildingName"=>"3A", 13554// "SecondaryStreet"=>"", 13555// "Street"=>"Blackheath Village", 13556// "Block"=>"", 13557// "Neighbourhood"=>"", 13558// "District"=>"", 13559// "City"=>"London", 13560// "Line1"=>"3A Blackheath Village", 13561// "Line2"=>"", 13562// "Line3"=>"", 13563// "Line4"=>"", 13564// "Line5"=>"", 13565// "AdminAreaName"=>"Greenwich", 13566// "AdminAreaCode"=>"", 13567// "Province"=>"", 13568// "ProvinceName"=>"", 13569// "ProvinceCode"=>"", 13570// "PostalCode"=>"SE3 9LA", 13571// "CountryName"=>"United Kingdom", 13572// "CountryIso2"=>"GB", 13573// "CountryIso3"=>"GBR", 13574// "CountryIsoNumber"=>"826", 13575// "SortingNumber1"=>"71124", 13576// "SortingNumber2"=>"", 13577// "Barcode"=>"(SE39LA2DH)", 13578// "POBoxNumber"=>"", 13579// "Label"=>"3A Blackheath Village\nLONDON\nSE3 9LA\nUNITED KINGDOM", 13580// "Type"=>"Residential", 13581// "DataLevel"=>"Premise", 13582// "Field1"=>"51.465613", 13583// "Field2"=>"0.009469", 13584// "Field3"=>"", 13585// "Field4"=>"", 13586// "Field5"=>"", 13587// "Field6"=>"", 13588// "Field7"=>"", 13589// "Field8"=>"", 13590// "Field9"=>"", 13591// "Field10"=>"", 13592// "Field11"=>"", 13593// "Field12"=>"", 13594// "Field13"=>"", 13595// "Field14"=>"", 13596// "Field15"=>"", 13597// "Field16"=>"", 13598// "Field17"=>"", 13599// "Field18"=>"", 13600// "Field19"=>"", 13601// "Field20"=>""},
13602// "channel"=>"sales", 13603// "notes"=>"", 13604// "mailOptin"=>"false", 13605// "chosenTime"=>"false", 13606// "chosenDate"=>"false", 13607// "noOfficeForPostcode"=>"false", 13608// "justContactMe"=>"false"}, 13609// "action"=>"index", 13610// "controller"=>"calendar_bookings"} 13611 13612HFBooking.Viewing = Object.create(HFBooking.Process, { 13613 step1: { value: new HFBooking.ViewStep(1) }, 13614 step2: { value: new HFBooking.ViewStep(2) }, 13615 step3: { value: new HFBooking.ViewStep(3) }, 13616 step4: { value: new HFBooking.ViewStep(4) }, 13617 property: { value: {} }, 13618 13619 events: { 13620 value: { 13621 'click .hfview__open': 'openModal', 13622 'click .hf-cal__close': 'closeModal', 13623 'click .hfview__back': 'previousStep', 13624 'click #hfview__nextmonth': 'nextMonth', 13625 'click #hfview__prevmonth': 'prevMonth', 13626 'click #hfview__nextweek': 'nextWeek', 13627 'click #hfview__prevweek': 'prevWeek', 13628 'click .hfview__month--day': 'selectWeek', 13629 'click .hfview__timeslot': 'selectTimeslot', 13630 'click #hfview__done-btn': 'done', 13631 'click #hfview__just-contact-me': 'justContactMe', 13632 'click #hf-cal__viewstep3__optin_label': 'toggleMarketingOptionView', 13633 'click #hf-cal__viewstep3__tandcs_label' : 'toggleTermsAndConditionsView', 13634 } 13635 }, 13636 13637 createModal: { 13638 value: function() { 13639 // build outer markup for the modal and append to the page: 13640 var $modalBg = $('<div id="hfview__bg" class="hf-cal inactive">'); 13641 var $window = $('<div class="hf-cal__window" style="z-index: 9999999999;">'); 13642 var $backdrop = $('<div class="hf-cal__backdrop">'); 13643 $window.append('<a href="#" class="hf-cal__close hfview__close"><p>×</p></a>');
13644 var $container = $('<div class="hf-cal__container viewing-form">'); 13645 $container.append('<div id="hfview__content" class="hf-cal__content">'); 13646 $($window).append($container); 13647 $($modalBg).append($window); 13648 $($modalBg).append($backdrop); 13649 $('body').append($modalBg); 13650 } 13651 }, 13652 13653 openModal: { 13654 value: function(e) { 13655 var $target = $(e.currentTarget); 13656 this.property.property_id = $target.data('property-id'); 13657 this.property.property_ref = $target.data('property-ref'); 13658 this.property.image = $target.data('property-image'); 13659 this.property.address = $target.data('property-address'); 13660 this.property.price = $target.data('property-price'); 13661 this.renderStep(1) 13662 $('#hfview__bg').removeClass('inactive'); 13663 } 13664 }, 13665 13666 closeModal: { 13667 value: function() { 13668 this.reset(); 13669 HFBooking.Viewing.currentStep = 1; 13670 $('#hfview__bg').addClass('inactive'); 13671 window.location.hash = ''; 13672 } 13673 }, 13674 13675 done: { 13676 value: function() { 13677 this.reset(); 13678 console.log('view done reset') 13679 this.closeModal(); 13680 } 13681 }, 13682 13683 reset: { 13684 value: function() { 13685 this.payload = { 13686 branchId: false, 13687 channel: '', 13688 addressData: {}, 13689 email: '', 13690 postcode_param: '', 13691 }; 13692 this.currentStep = 1; 13693 this.addresses = []; 13694 this.calendarData = { 13695 currentMonth: new Date().getMonth(), 13696 }; 13697 this.selectedWeek = false; 13698 this.selectedTimeslot = { 13699 day: false, 13700 hours: false, 13701 minutes: false, 13702 }; 13703 } 13704 }, 13705 13706 previousStep: { 13707 value: function(e) { 13708 this.updatePayloadFromFields(); 13709 e.preventDefault(); 13710 if (this.payload.justContactMe || this.currentStep === 3 && this.calendarData.days && this.calendarData.days.success) { 13711 this.currentStep--; 13712 } 13713 this['step' + this.currentStep].render(); 13714 } 13715 }, 13716 13717 nextStep: { 13718 value: function() { 13719 this.updatePayloadFromFields(); 13720 console.log(this.currentStep); 13721 if (this['step' + this.currentStep].validate()) { 13722 switch (this.currentStep) { 13723 case 1: 13724 this.currentStep++; 13725 this.getDates(); 13726 break; 13727 case 3: 13728 this.sendPayload(); 13729 break; 13730 default: 13731 this.currentStep++; 13732 this.renderStep(this.currentStep); 13733 break; 13734 } 13735 } else { 13736 $('.hf-cal__form-button').removeAttr('disabled'); 13737 console.log('Failed validation'); 13738 } 13739 } 13740 }, 13741 13742 updatePayloadFromFields: { 13743 value: function() { 13744 var $fields = $('[data-hfviewing]'); 13745 for (var i=0; i<$fields.length; i++) { 13746 var $field = $($fields[i]); 13747 this.updatePayload($field.data('hfviewing'), $field.val()); 13748 } 13749 var $addressFields = $('[data-hfviewing-address]'); 13750 for (var i=0; i<$addressFields.length; i++) { 13751 var $field = $($addressFields[i]); 13752 this.updateAddress($field.data('hfviewing-address'), $field.val()); 13753 } 13754 var $fields = $('[data-hfviewing-intention]'); 13755 for (var i=0; i<$fields.length; i++) { 13756 var $field = $($fields[i]) 13757 if ($field.prop('checked')) { 13758 this.updatePayload($field.data('hfviewing-intention'), $field.val()); 13759 } 13760 } 13761 } 13762 }, 13763 13764 getDates: { 13765 value: function() { 13766 console.log('Getting dates...'); 13767 13768 // show loading spinner 13769 $('.hf-cal__content').html('<div class="hfcal__loader"><div class="hfcal__loader-inner"></div></div>'); 13770 13771 if (!this.wcDate) { this.wcDate = this.getStartOfWeek(new Date()); } // this needs to be START of week - does it? 13772 13773 console.log(this.wcDate); 13774 13775 wc = { 13776 y: this.wcDate.getFullYear(), 13777 m: this.wcDate.getMonth(), 13778 d: this.wcDate.getDate(), 13779 }; 13780 var requestData = { wc: wc, property: this.property } 13781 var _this = this; 13782 // make AJAX request to get timeslots from Ctesius / Reapit: 13783 $.getJSON('/calendar_bookings', requestData, function(data) { 13784 _this.addBranchDetails(_this.payload, data) 13785 if (data.error) { 13786 console.log("Response: ", data.error) 13787 _this.payload.justContactMe = true; 13788 _this.currentStep++; 13789 _this.renderStep(3); 13790 } else { 13791 _this.payload.hfOnlyCal = data.hf_only_cal; 13792 _this.calendarData.days = data.days; 13793 // TODO: What if the week straddles 2 different years? data.days[0].y might be wrong one... 13794 _this.calendarData.monthData = _this.buildMonth(_this.calendarData.currentMonth, data.days.appointments[1].y); 13795 _this.payload.officeCode = data.office_code; //Reapit Agents only 13796 _this.currentStep = 2; 13797 _this.renderStep(2); 13798 } 13799 }); 13800 } 13801 }, 13802 13803 sendPayload: { 13804 value: function() { 13805 _this = this; 13806 _this.payload.property = this.property 13807 // show loading spinner 13808 $('.hf-cal__content').html('<div class="hfcal__loader"><div class="hfcal__loader-inner"></div></div>'); 13809 $.ajax({ 13810 url: '/calendar_bookings', 13811 method: 'POST', 13812 data: this.payload, 13813 success: function(response) { 13814 if(response.error){ 13815 _this.handleError(response); 13816 }else{ 13817 _this.office = HFBooking.Viewing.payload.branch; 13818 _this.error = false;
13819 Ctesius.kickEvent('calendar_booking_complete', _this.payload, 'Viewing'); 13820 _this.renderStep(4); 13821 } 13822 }, 13823 }) 13824 } 13825 }, 13826 13827 handleError: { 13828 value: function(response) { 13829 _this.error = true; 13830 _this.office = HFBooking.Viewing.payload.branch; 13831 if (response.error === 'Negotiator unavailable at this time'){ 13832 var month = HFBooking.Viewing.selectedTimeslot.month + 1 13833 var date = HFBooking.Viewing.selectedTimeslot.day + '-' + month + '-' + HFBooking.Viewing.selectedTimeslot.year; 13834 var date_time = HFBooking.Viewing.payload.chosenTime + ' on ' + date; 13835 _this.errorMessage = 'Selected time of ' + date_time + ' is unavailable. Please choose a different time.'; 13836 _this.getDates(); 13837 }else{ 13838 _this.renderStep(4); 13839 } 13840 } 13841 } 13842}); 13843 13844$(function() { 13845 // create the modal if we detect a link to open it on the page 13846 console.log('JS Loaded'); 13847 13848 if ($('.hfval__open').length > 0 || window.hfValSelector) { 13849 HFBooking.Valuation.createModal(); 13850 } 13851 13852 $('body').on('submit', '.hfval__form', function(e) { 13853 e.preventDefault(); 13854 e.target.getElementsByClassName('hf-cal__form-button')[0].disabled = 'true' 13855 HFBooking.Valuation.nextStep(); 13856 }); 13857 13858 $('body').on('submit', '.hfview__form', function(e) { 13859 e.preventDefault(); 13860 e.target.getElementsByClassName('hf-cal__form-button')[0].disabled = 'true' 13861 HFBooking.Viewing.nextStep(); 13862 }); 13863 13864 $('body').on('change', '.hfval__channel', function(e) { 13865 HFBooking.Valuation.payload.channel = e.currentTarget.value; 13866 }); 13867 13868 $('body').on('change', '.hfval__intention', function(e) { 13869 HFBooking.Valuation.payload.intention = e.currentTarget.value; 13870 }); 13871 13872 $('body').on('change', '.hfview__intention', function(e) { 13873 HFBooking.Viewing.payload.intention = e.currentTarget.value; 13874 }); 13875 13876 // loop through the events and create jQuery event listeners 13877 for (e in HFBooking.Valuation.events) { 13878 if (HFBooking.Valuation.events.hasOwnProperty(e)) { 13879 var arr = e.split(' '); 13880 var callback = HFBooking.Valuation[HFBooking.Valuation.events[e]] 13881 .bind(HFBooking.Valuation); 13882 $('body').on(arr[0], arr[1], callback); 13883 } 13884 }; 13885 13886 if (window.hfValSelector) { 13887 console.log('Found button selector, adding event listener...'); 13888 $('body').on('click', window.hfValSelector, HFBooking.Valuation.openModal.bind(HFBooking.Valuation)); 13889 } 13890 13891 if ($('.hfview__open').length > 0) { 13892 HFBooking.Viewing.createModal(); 13893 } 13894 13895 for (e in HFBooking.Viewing.events) { 13896 if (HFBooking.Viewing.events.hasOwnProperty(e)) { 13897 var arr = e.split(' '); 13898 var callback = HFBooking.Viewing[HFBooking.Viewing.events[e]] 13899 .bind(HFBooking.Viewing); 13900 $('body').on(arr[0], arr[1], callback); 13901 } 13902 }; 13903 13904});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.