vendor: 113,528 bytes, lines 1-4080
1/* Minification failed. Returning unminified contents. 2(32337,9-15): run-time error JS1300: Strict-mode does not allow assignment to undefined variables: Base64 3 */ 4/*! 5 * jQuery JavaScript Library v3.7.1 6 * https://jquery.com/ 7 * 8 * Copyright OpenJS Foundation and other contributors 9 * Released under the MIT license 10 * https://jquery.org/license 11 * 12 * Date: 2023-08-28T13:37Z 13 */ 14( function( global, factory ) { 15 16 "use strict"; 17 18 if ( typeof module === "object" && typeof module.exports === "object" ) { 19 20 // For CommonJS and CommonJS-like environments where a proper `window` 21 // is present, execute the factory and get jQuery. 22 // For environments that do not have a `window` with a `document` 23 // (such as Node.js), expose a factory as module.exports. 24 // This accentuates the need for the creation of a real `window`. 25 // e.g. var jQuery = require("jquery")(window); 26 // See ticket trac-14549 for more info. 27 module.exports = global.document ? 28 factory( global, true ) : 29 function( w ) { 30 if ( !w.document ) { 31 throw new Error( "jQuery requires a window with a document" ); 32 } 33 return factory( w ); 34 }; 35 } else { 36 factory( global ); 37 } 38 39// Pass this if window is not defined yet 40} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { 41 42// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 43// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode 44// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common 45// enough that all such attempts are guarded in a try block. 46"use strict"; 47 48var arr = []; 49 50var getProto = Object.getPrototypeOf; 51 52var slice = arr.slice; 53 54var flat = arr.flat ? function( array ) { 55 return arr.flat.call( array ); 56} : function( array ) { 57 return arr.concat.apply( [], array ); 58}; 59 60 61var push = arr.push; 62 63var indexOf = arr.indexOf; 64 65var class2type = {}; 66 67var toString = class2type.toString; 68 69var hasOwn = class2type.hasOwnProperty; 70 71var fnToString = hasOwn.toString; 72 73var ObjectFunctionString = fnToString.call( Object ); 74 75var support = {}; 76 77var isFunction = function isFunction( obj ) { 78 79 // Support: Chrome <=57, Firefox <=52 80 // In some browsers, typeof returns "function" for HTML <object> elements 81 // (i.e., `typeof document.createElement( "object" ) === "function"`). 82 // We don't want to classify *any* DOM node as a function. 83 // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 84 // Plus for old WebKit, typeof returns "function" for HTML collections 85 // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) 86 return typeof obj === "function" && typeof obj.nodeType !== "number" && 87 typeof obj.item !== "function"; 88 }; 89 90 91var isWindow = function isWindow( obj ) { 92 return obj != null && obj === obj.window; 93 }; 94 95 96var document = window.document; 97 98 99 100 var preservedScriptAttributes = { 101 type: true, 102 src: true, 103 nonce: true, 104 noModule: true 105 }; 106 107 function DOMEval( code, node, doc ) { 108 doc = doc || document; 109 110 var i, val, 111 script = doc.createElement( "script" ); 112 113 script.text = code; 114 if ( node ) { 115 for ( i in preservedScriptAttributes ) { 116 117 // Support: Firefox 64+, Edge 18+ 118 // Some browsers don't support the "nonce" property on scripts. 119 // On the other hand, just using `getAttribute` is not enough as 120 // the `nonce` attribute is reset to an empty string whenever it 121 // becomes browsing-context connected. 122 // See https://github.com/whatwg/html/issues/2369 123 // See https://html.spec.whatwg.org/#nonce-attributes 124 // The `node.getAttribute` check was added for the sake of 125 // `jQuery.globalEval` so that it can fake a nonce-containing node 126 // via an object. 127 val = node[ i ] || node.getAttribute && node.getAttribute( i ); 128 if ( val ) { 129 script.setAttribute( i, val ); 130 } 131 } 132 } 133 doc.head.appendChild( script ).parentNode.removeChild( script ); 134 } 135 136 137function toType( obj ) { 138 if ( obj == null ) { 139 return obj + ""; 140 } 141 142 // Support: Android <=2.3 only (functionish RegExp) 143 return typeof obj === "object" || typeof obj === "function" ? 144 class2type[ toString.call( obj ) ] || "object" : 145 typeof obj; 146} 147/* global Symbol */ 148// Defining this global in .eslintrc.json would create a danger of using the global 149// unguarded in another place, it seems safer to define global only for this module 150 151 152 153var version = "3.7.1", 154 155 rhtmlSuffix = /HTML$/i, 156 157 // Define a local copy of jQuery 158 jQuery = function( selector, context ) { 159 160 // The jQuery object is actually just the init constructor 'enhanced' 161 // Need init if jQuery is called (just allow error to be thrown if not included) 162 return new jQuery.fn.init( selector, context ); 163 }; 164 165jQuery.fn = jQuery.prototype = { 166 167 // The current version of jQuery being used 168 jquery: version, 169 170 constructor: jQuery, 171 172 // The default length of a jQuery object is 0 173 length: 0, 174 175 toArray: function() { 176 return slice.call( this ); 177 }, 178 179 // Get the Nth element in the matched element set OR 180 // Get the whole matched element set as a clean array 181 get: function( num ) { 182 183 // Return all the elements in a clean array 184 if ( num == null ) { 185 return slice.call( this ); 186 } 187 188 // Return just the one element from the set 189 return num < 0 ? this[ num + this.length ] : this[ num ]; 190 }, 191 192 // Take an array of elements and push it onto the stack 193 // (returning the new matched element set) 194 pushStack: function( elems ) { 195 196 // Build a new jQuery matched element set 197 var ret = jQuery.merge( this.constructor(), elems ); 198 199 // Add the old object onto the stack (as a reference) 200 ret.prevObject = this; 201 202 // Return the newly-formed element set 203 return ret; 204 }, 205 206 // Execute a callback for every element in the matched set. 207 each: function( callback ) { 208 return jQuery.each( this, callback ); 209 }, 210 211 map: function( callback ) { 212 return this.pushStack( jQuery.map( this, function( elem, i ) { 213 return callback.call( elem, i, elem ); 214 } ) ); 215 }, 216 217 slice: function() { 218 return this.pushStack( slice.apply( this, arguments ) ); 219 }, 220 221 first: function() { 222 return this.eq( 0 ); 223 }, 224 225 last: function() { 226 return this.eq( -1 ); 227 }, 228 229 even: function() { 230 return this.pushStack( jQuery.grep( this, function( _elem, i ) { 231 return ( i + 1 ) % 2; 232 } ) ); 233 }, 234 235 odd: function() { 236 return this.pushStack( jQuery.grep( this, function( _elem, i ) { 237 return i % 2; 238 } ) ); 239 }, 240 241 eq: function( i ) { 242 var len = this.length, 243 j = +i + ( i < 0 ? len : 0 ); 244 return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); 245 }, 246 247 end: function() { 248 return this.prevObject || this.constructor(); 249 }, 250 251 // For internal use only. 252 // Behaves like an Array's method, not like a jQuery method. 253 push: push, 254 sort: arr.sort, 255 splice: arr.splice 256}; 257 258jQuery.extend = jQuery.fn.extend = function() { 259 var options, name, src, copy, copyIsArray, clone, 260 target = arguments[ 0 ] || {}, 261 i = 1, 262 length = arguments.length, 263 deep = false; 264 265 // Handle a deep copy situation 266 if ( typeof target === "boolean" ) { 267 deep = target; 268 269 // Skip the boolean and the target 270 target = arguments[ i ] || {}; 271 i++; 272 } 273 274 // Handle case when target is a string or something (possible in deep copy) 275 if ( typeof target !== "object" && !isFunction( target ) ) { 276 target = {}; 277 } 278 279 // Extend jQuery itself if only one argument is passed 280 if ( i === length ) { 281 target = this; 282 i--; 283 } 284 285 for ( ; i < length; i++ ) { 286 287 // Only deal with non-null/undefined values 288 if ( ( options = arguments[ i ] ) != null ) { 289 290 // Extend the base object 291 for ( name in options ) { 292 copy = options[ name ]; 293 294 // Prevent Object.prototype pollution 295 // Prevent never-ending loop 296 if ( name === "__proto__" || target === copy ) { 297 continue; 298 } 299 300 // Recurse if we're merging plain objects or arrays 301 if ( deep && copy && ( jQuery.isPlainObject( copy ) || 302 ( copyIsArray = Array.isArray( copy ) ) ) ) { 303 src = target[ name ]; 304 305 // Ensure proper type for the source value 306 if ( copyIsArray && !Array.isArray( src ) ) { 307 clone = []; 308 } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { 309 clone = {}; 310 } else { 311 clone = src; 312 } 313 copyIsArray = false; 314 315 // Never move original objects, clone them 316 target[ name ] = jQuery.extend( deep, clone, copy ); 317 318 // Don't bring in undefined values 319 } else if ( copy !== undefined ) { 320 target[ name ] = copy; 321 } 322 } 323 } 324 } 325 326 // Return the modified object 327 return target; 328}; 329 330jQuery.extend( { 331 332 // Unique for each copy of jQuery on the page 333 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), 334 335 // Assume jQuery is ready without the ready module 336 isReady: true, 337 338 error: function( msg ) { 339 throw new Error( msg ); 340 }, 341 342 noop: function() {}, 343 344 isPlainObject: function( obj ) { 345 var proto, Ctor; 346 347 // Detect obvious negatives 348 // Use toString instead of jQuery.type to catch host objects 349 if ( !obj || toString.call( obj ) !== "[object Object]" ) { 350 return false; 351 } 352 353 proto = getProto( obj ); 354 355 // Objects with no prototype (e.g., `Object.create( null )`) are plain 356 if ( !proto ) { 357 return true; 358 } 359 360 // Objects with prototype are plain iff they were constructed by a global Object function 361 Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; 362 return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; 363 }, 364 365 isEmptyObject: function( obj ) { 366 var name; 367 368 for ( name in obj ) { 369 return false; 370 } 371 return true; 372 }, 373 374 // Evaluates a script in a provided context; falls back to the global one 375 // if not specified. 376 globalEval: function( code, options, doc ) { 377 DOMEval( code, { nonce: options && options.nonce }, doc ); 378 }, 379 380 each: function( obj, callback ) { 381 var length, i = 0; 382 383 if ( isArrayLike( obj ) ) { 384 length = obj.length; 385 for ( ; i < length; i++ ) { 386 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { 387 break; 388 } 389 } 390 } else { 391 for ( i in obj ) { 392 if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { 393 break; 394 } 395 } 396 } 397 398 return obj; 399 }, 400 401 402 // Retrieve the text value of an array of DOM nodes 403 text: function( elem ) { 404 var node, 405 ret = "", 406 i = 0, 407 nodeType = elem.nodeType; 408 409 if ( !nodeType ) { 410 411 // If no nodeType, this is expected to be an array 412 while ( ( node = elem[ i++ ] ) ) { 413 414 // Do not traverse comment nodes 415 ret += jQuery.text( node ); 416 } 417 } 418 if ( nodeType === 1 || nodeType === 11 ) { 419 return elem.textContent; 420 } 421 if ( nodeType === 9 ) { 422 return elem.documentElement.textContent; 423 } 424 if ( nodeType === 3 || nodeType === 4 ) { 425 return elem.nodeValue; 426 } 427 428 // Do not include comment or processing instruction nodes 429 430 return ret; 431 }, 432 433 // results is for internal usage only 434 makeArray: function( arr, results ) { 435 var ret = results || []; 436 437 if ( arr != null ) { 438 if ( isArrayLike( Object( arr ) ) ) { 439 jQuery.merge( ret, 440 typeof arr === "string" ? 441 [ arr ] : arr 442 ); 443 } else { 444 push.call( ret, arr ); 445 } 446 } 447 448 return ret; 449 }, 450 451 inArray: function( elem, arr, i ) { 452 return arr == null ? -1 : indexOf.call( arr, elem, i ); 453 }, 454 455 isXMLDoc: function( elem ) { 456 var namespace = elem && elem.namespaceURI, 457 docElem = elem && ( elem.ownerDocument || elem ).documentElement; 458 459 // Assume HTML when documentElement doesn't yet exist, such as inside 460 // document fragments. 461 return !rhtmlSuffix.test( namespace || docElem && docElem.nodeName || "HTML" ); 462 }, 463 464 // Support: Android <=4.0 only, PhantomJS 1 only 465 // push.apply(_, arraylike) throws on ancient WebKit 466 merge: function( first, second ) { 467 var len = +second.length, 468 j = 0, 469 i = first.length; 470 471 for ( ; j < len; j++ ) { 472 first[ i++ ] = second[ j ]; 473 } 474 475 first.length = i; 476 477 return first; 478 }, 479 480 grep: function( elems, callback, invert ) { 481 var callbackInverse, 482 matches = [], 483 i = 0, 484 length = elems.length, 485 callbackExpect = !invert; 486 487 // Go through the array, only saving the items 488 // that pass the validator function 489 for ( ; i < length; i++ ) { 490 callbackInverse = !callback( elems[ i ], i ); 491 if ( callbackInverse !== callbackExpect ) { 492 matches.push( elems[ i ] ); 493 } 494 } 495 496 return matches; 497 }, 498 499 // arg is for internal usage only 500 map: function( elems, callback, arg ) { 501 var length, value, 502 i = 0, 503 ret = []; 504 505 // Go through the array, translating each of the items to their new values 506 if ( isArrayLike( elems ) ) { 507 length = elems.length; 508 for ( ; i < length; i++ ) { 509 value = callback( elems[ i ], i, arg ); 510 511 if ( value != null ) { 512 ret.push( value ); 513 } 514 } 515 516 // Go through every key on the object, 517 } else { 518 for ( i in elems ) { 519 value = callback( elems[ i ], i, arg ); 520 521 if ( value != null ) { 522 ret.push( value ); 523 } 524 } 525 } 526 527 // Flatten any nested arrays 528 return flat( ret ); 529 }, 530 531 // A global GUID counter for objects 532 guid: 1, 533 534 // jQuery.support is not used in Core but other projects attach their 535 // properties to it so it needs to exist. 536 support: support 537} ); 538 539if ( typeof Symbol === "function" ) { 540 jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; 541} 542 543// Populate the class2type map 544jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), 545 function( _i, name ) { 546 class2type[ "[object " + name + "]" ] = name.toLowerCase(); 547 } ); 548 549function isArrayLike( obj ) { 550 551 // Support: real iOS 8.2 only (not reproducible in simulator) 552 // `in` check used to prevent JIT error (gh-2145) 553 // hasOwn isn't used here due to false negatives 554 // regarding Nodelist length in IE 555 var length = !!obj && "length" in obj && obj.length, 556 type = toType( obj ); 557 558 if ( isFunction( obj ) || isWindow( obj ) ) { 559 return false; 560 } 561 562 return type === "array" || length === 0 || 563 typeof length === "number" && length > 0 && ( length - 1 ) in obj; 564} 565 566 567function nodeName( elem, name ) { 568 569 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); 570 571} 572var pop = arr.pop; 573 574 575var sort = arr.sort; 576 577 578var splice = arr.splice; 579 580 581var whitespace = "[\\x20\\t\\r\\n\\f]"; 582 583 584var rtrimCSS = new RegExp( 585 "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", 586 "g" 587); 588 589 590 591 592// Note: an element does not contain itself 593jQuery.contains = function( a, b ) { 594 var bup = b && b.parentNode; 595 596 return a === bup || !!( bup && bup.nodeType === 1 && ( 597 598 // Support: IE 9 - 11+ 599 // IE doesn't have `contains` on SVG. 600 a.contains ? 601 a.contains( bup ) : 602 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 603 ) ); 604}; 605 606 607 608 609// CSS string/identifier serialization 610// https://drafts.csswg.org/cssom/#common-serializing-idioms 611var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g; 612 613function fcssescape( ch, asCodePoint ) { 614 if ( asCodePoint ) { 615 616 // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER 617 if ( ch === "\0" ) { 618 return "\uFFFD"; 619 } 620 621 // Control characters and (dependent upon position) numbers get escaped as code points 622 return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; 623 } 624 625 // Other potentially-special ASCII characters get backslash-escaped 626 return "\\" + ch; 627} 628 629jQuery.escapeSelector = function( sel ) { 630 return ( sel + "" ).replace( rcssescape, fcssescape ); 631}; 632 633 634 635 636var preferredDoc = document, 637 pushNative = push; 638 639( function() { 640 641var i, 642 Expr, 643 outermostContext, 644 sortInput, 645 hasDuplicate, 646 push = pushNative, 647 648 // Local document vars 649 document, 650 documentElement, 651 documentIsHTML, 652 rbuggyQSA, 653 matches, 654 655 // Instance-specific data 656 expando = jQuery.expando, 657 dirruns = 0, 658 done = 0, 659 classCache = createCache(), 660 tokenCache = createCache(), 661 compilerCache = createCache(), 662 nonnativeSelectorCache = createCache(), 663 sortOrder = function( a, b ) { 664 if ( a === b ) { 665 hasDuplicate = true; 666 } 667 return 0; 668 }, 669 670 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|" + 671 "loop|multiple|open|readonly|required|scoped", 672 673 // Regular expressions 674 675 // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram 676 identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + 677 "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", 678 679 // Attribute selectors: https://www.w3.org/TR/selectors/#attribute-selectors 680 attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + 681 682 // Operator (capture 2) 683 "*([*^$|!~]?=)" + whitespace + 684 685 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" 686 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + 687 whitespace + "*\\]", 688 689 pseudos = ":(" + identifier + ")(?:\\((" + 690 691 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: 692 // 1. quoted (capture 3; capture 4 or capture 5) 693 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + 694 695 // 2. simple (capture 6) 696 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + 697 698 // 3. anything else (capture 2) 699 ".*" + 700 ")\\)|)", 701 702 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter 703 rwhitespace = new RegExp( whitespace + "+", "g" ), 704 705 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), 706 rleadingCombinator = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + 707 whitespace + "*" ), 708 rdescend = new RegExp( whitespace + "|>" ), 709 710 rpseudo = new RegExp( pseudos ), 711 ridentifier = new RegExp( "^" + identifier + "$" ), 712 713 matchExpr = { 714 ID: new RegExp( "^#(" + identifier + ")" ), 715 CLASS: new RegExp( "^\\.(" + identifier + ")" ), 716 TAG: new RegExp( "^(" + identifier + "|[*])" ), 717 ATTR: new RegExp( "^" + attributes ), 718 PSEUDO: new RegExp( "^" + pseudos ), 719 CHILD: new RegExp( 720 "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + 721 whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + 722 whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), 723 bool: new RegExp( "^(?:" + booleans + ")$", "i" ), 724 725 // For use in libraries implementing .is() 726 // We use this for POS matching in `select` 727 needsContext: new RegExp( "^" + whitespace + 728 "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + 729 "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) 730 }, 731 732 rinputs = /^(?:input|select|textarea|button)$/i, 733 rheader = /^h\d$/i, 734 735 // Easily-parseable/retrievable ID or TAG or CLASS selectors 736 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, 737 738 rsibling = /[+~]/, 739 740 // CSS escapes 741 // https://www.w3.org/TR/CSS21/syndata.html#escaped-characters 742 runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + 743 "?|\\\\([^\\r\\n\\f])", "g" ), 744 funescape = function( escape, nonHex ) { 745 var high = "0x" + escape.slice( 1 ) - 0x10000; 746 747 if ( nonHex ) { 748 749 // Strip the backslash prefix from a non-hex escape sequence 750 return nonHex; 751 } 752 753 // Replace a hexadecimal escape sequence with the encoded Unicode code point 754 // Support: IE <=11+ 755 // For values outside the Basic Multilingual Plane (BMP), manually construct a 756 // surrogate pair 757 return high < 0 ? 758 String.fromCharCode( high + 0x10000 ) : 759 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); 760 }, 761 762 // Used for iframes; see `setDocument`. 763 // Support: IE 9 - 11+, Edge 12 - 18+ 764 // Removing the function wrapper causes a "Permission Denied" 765 // error in IE/Edge. 766 unloadHandler = function() { 767 setDocument(); 768 }, 769 770 inDisabledFieldset = addCombinator( 771 function( elem ) { 772 return elem.disabled === true && nodeName( elem, "fieldset" ); 773 }, 774 { dir: "parentNode", next: "legend" } 775 ); 776 777// Support: IE <=9 only 778// Accessing document.activeElement can throw unexpectedly 779// https://bugs.jquery.com/ticket/13393 780function safeActiveElement() { 781 try { 782 return document.activeElement; 783 } catch ( err ) { } 784} 785 786// Optimize for push.apply( _, NodeList ) 787try { 788 push.apply( 789 ( arr = slice.call( preferredDoc.childNodes ) ), 790 preferredDoc.childNodes 791 ); 792 793 // Support: Android <=4.0 794 // Detect silently failing push.apply 795 // eslint-disable-next-line no-unused-expressions 796 arr[ preferredDoc.childNodes.length ].nodeType; 797} catch ( e ) { 798 push = { 799 apply: function( target, els ) { 800 pushNative.apply( target, slice.call( els ) ); 801 }, 802 call: function( target ) { 803 pushNative.apply( target, slice.call( arguments, 1 ) ); 804 } 805 }; 806} 807 808function find( selector, context, results, seed ) { 809 var m, i, elem, nid, match, groups, newSelector, 810 newContext = context && context.ownerDocument, 811 812 // nodeType defaults to 9, since context defaults to document 813 nodeType = context ? context.nodeType : 9; 814 815 results = results || []; 816 817 // Return early from calls with invalid selector or context 818 if ( typeof selector !== "string" || !selector || 819 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { 820 821 return results; 822 } 823 824 // Try to shortcut find operations (as opposed to filters) in HTML documents 825 if ( !seed ) { 826 setDocument( context ); 827 context = context || document; 828 829 if ( documentIsHTML ) { 830 831 // If the selector is sufficiently simple, try using a "get*By*" DOM method 832 // (excepting DocumentFragment context, where the methods don't exist) 833 if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { 834 835 // ID selector 836 if ( ( m = match[ 1 ] ) ) { 837 838 // Document context 839 if ( nodeType === 9 ) { 840 if ( ( elem = context.getElementById( m ) ) ) { 841 842 // Support: IE 9 only 843 // getElementById can match elements by name instead of ID 844 if ( elem.id === m ) { 845 push.call( results, elem ); 846 return results; 847 } 848 } else { 849 return results; 850 } 851 852 // Element context 853 } else { 854 855 // Support: IE 9 only 856 // getElementById can match elements by name instead of ID 857 if ( newContext && ( elem = newContext.getElementById( m ) ) && 858 find.contains( context, elem ) && 859 elem.id === m ) { 860 861 push.call( results, elem ); 862 return results; 863 } 864 } 865 866 // Type selector 867 } else if ( match[ 2 ] ) { 868 push.apply( results, context.getElementsByTagName( selector ) ); 869 return results; 870 871 // Class selector 872 } else if ( ( m = match[ 3 ] ) && context.getElementsByClassName ) { 873 push.apply( results, context.getElementsByClassName( m ) ); 874 return results; 875 } 876 } 877 878 // Take advantage of querySelectorAll 879 if ( !nonnativeSelectorCache[ selector + " " ] && 880 ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) ) { 881 882 newSelector = selector; 883 newContext = context; 884 885 // qSA considers elements outside a scoping root when evaluating child or 886 // descendant combinators, which is not what we want. 887 // In such cases, we work around the behavior by prefixing every selector in the 888 // list with an ID selector referencing the scope context. 889 // The technique has to be used as well when a leading combinator is used 890 // as such selectors are not recognized by querySelectorAll. 891 // Thanks to Andrew Dupont for this technique. 892 if ( nodeType === 1 && 893 ( rdescend.test( selector ) || rleadingCombinator.test( selector ) ) ) { 894 895 // Expand context for sibling selectors 896 newContext = rsibling.test( selector ) && testContext( context.parentNode ) || 897 context; 898 899 // We can use :scope instead of the ID hack if the browser 900 // supports it & if we're not changing the context. 901 // Support: IE 11+, Edge 17 - 18+ 902 // IE/Edge sometimes throw a "Permission denied" error when 903 // strict-comparing two documents; shallow comparisons work. 904 // eslint-disable-next-line eqeqeq 905 if ( newContext != context || !support.scope ) { 906 907 // Capture the context ID, setting it first if necessary 908 if ( ( nid = context.getAttribute( "id" ) ) ) { 909 nid = jQuery.escapeSelector( nid ); 910 } else { 911 context.setAttribute( "id", ( nid = expando ) ); 912 } 913 } 914 915 // Prefix every selector in the list 916 groups = tokenize( selector ); 917 i = groups.length; 918 while ( i-- ) { 919 groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + 920 toSelector( groups[ i ] ); 921 } 922 newSelector = groups.join( "," ); 923 } 924 925 try { 926 push.apply( results, 927 newContext.querySelectorAll( newSelector ) 928 ); 929 return results; 930 } catch ( qsaError ) { 931 nonnativeSelectorCache( selector, true ); 932 } finally { 933 if ( nid === expando ) { 934 context.removeAttribute( "id" ); 935 } 936 } 937 } 938 } 939 } 940 941 // All others 942 return select( selector.replace( rtrimCSS, "$1" ), context, results, seed ); 943} 944 945/** 946 * Create key-value caches of limited size 947 * @returns {function(string, object)} Returns the Object data after storing it on itself with 948 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) 949 * deleting the oldest entry 950 */ 951function createCache() { 952 var keys = []; 953 954 function cache( key, value ) { 955 956 // Use (key + " ") to avoid collision with native prototype properties 957 // (see https://github.com/jquery/sizzle/issues/157) 958 if ( keys.push( key + " " ) > Expr.cacheLength ) { 959 960 // Only keep the most recent entries 961 delete cache[ keys.shift() ]; 962 } 963 return ( cache[ key + " " ] = value ); 964 } 965 return cache; 966} 967 968/** 969 * Mark a function for special use by jQuery selector module 970 * @param {Function} fn The function to mark 971 */ 972function markFunction( fn ) { 973 fn[ expando ] = true; 974 return fn; 975} 976 977/** 978 * Support testing using an element 979 * @param {Function} fn Passed the created element and returns a boolean result 980 */ 981function assert( fn ) { 982 var el = document.createElement( "fieldset" ); 983 984 try { 985 return !!fn( el ); 986 } catch ( e ) { 987 return false; 988 } finally { 989 990 // Remove from its parent by default 991 if ( el.parentNode ) { 992 el.parentNode.removeChild( el ); 993 } 994 995 // release memory in IE 996 el = null; 997 } 998} 999 1000/** 1001 * Returns a function to use in pseudos for input types 1002 * @param {String} type 1003 */ 1004function createInputPseudo( type ) { 1005 return function( elem ) { 1006 return nodeName( elem, "input" ) && elem.type === type; 1007 }; 1008} 1009 1010/** 1011 * Returns a function to use in pseudos for buttons 1012 * @param {String} type 1013 */ 1014function createButtonPseudo( type ) { 1015 return function( elem ) { 1016 return ( nodeName( elem, "input" ) || nodeName( elem, "button" ) ) && 1017 elem.type === type; 1018 }; 1019} 1020 1021/** 1022 * Returns a function to use in pseudos for :enabled/:disabled 1023 * @param {Boolean} disabled true for :disabled; false for :enabled 1024 */ 1025function createDisabledPseudo( disabled ) { 1026 1027 // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable 1028 return function( elem ) { 1029 1030 // Only certain elements can match :enabled or :disabled 1031 // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled 1032 // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled 1033 if ( "form" in elem ) { 1034 1035 // Check for inherited disabledness on relevant non-disabled elements: 1036 // * listed form-associated elements in a disabled fieldset 1037 // https://html.spec.whatwg.org/multipage/forms.html#category-listed 1038 // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled 1039 // * option elements in a disabled optgroup 1040 // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled 1041 // All such elements have a "form" property. 1042 if ( elem.parentNode && elem.disabled === false ) { 1043 1044 // Option elements defer to a parent optgroup if present 1045 if ( "label" in elem ) { 1046 if ( "label" in elem.parentNode ) { 1047 return elem.parentNode.disabled === disabled; 1048 } else { 1049 return elem.disabled === disabled; 1050 } 1051 } 1052 1053 // Support: IE 6 - 11+ 1054 // Use the isDisabled shortcut property to check for disabled fieldset ancestors 1055 return elem.isDisabled === disabled || 1056 1057 // Where there is no isDisabled, check manually 1058 elem.isDisabled !== !disabled && 1059 inDisabledFieldset( elem ) === disabled; 1060 } 1061 1062 return elem.disabled === disabled; 1063 1064 // Try to winnow out elements that can't be disabled before trusting the disabled property. 1065 // Some victims get caught in our net (label, legend, menu, track), but it shouldn't 1066 // even exist on them, let alone have a boolean value. 1067 } else if ( "label" in elem ) { 1068 return elem.disabled === disabled; 1069 } 1070 1071 // Remaining elements are neither :enabled nor :disabled 1072 return false; 1073 }; 1074} 1075 1076/** 1077 * Returns a function to use in pseudos for positionals 1078 * @param {Function} fn 1079 */ 1080function createPositionalPseudo( fn ) { 1081 return markFunction( function( argument ) { 1082 argument = +argument; 1083 return markFunction( function( seed, matches ) { 1084 var j, 1085 matchIndexes = fn( [], seed.length, argument ), 1086 i = matchIndexes.length; 1087 1088 // Match elements found at the specified indexes 1089 while ( i-- ) { 1090 if ( seed[ ( j = matchIndexes[ i ] ) ] ) { 1091 seed[ j ] = !( matches[ j ] = seed[ j ] ); 1092 } 1093 } 1094 } ); 1095 } ); 1096} 1097 1098/** 1099 * Checks a node for validity as a jQuery selector context 1100 * @param {Element|Object=} context 1101 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value 1102 */ 1103function testContext( context ) { 1104 return context && typeof context.getElementsByTagName !== "undefined" && context; 1105} 1106 1107/** 1108 * Sets document-related variables once based on the current document 1109 * @param {Element|Object} [node] An element or document object to use to set the document 1110 * @returns {Object} Returns the current document 1111 */ 1112function setDocument( node ) { 1113 var subWindow, 1114 doc = node ? node.ownerDocument || node : preferredDoc; 1115 1116 // Return early if doc is invalid or already selected 1117 // Support: IE 11+, Edge 17 - 18+ 1118 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing 1119 // two documents; shallow comparisons work. 1120 // eslint-disable-next-line eqeqeq 1121 if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { 1122 return document; 1123 } 1124 1125 // Update global variables 1126 document = doc; 1127 documentElement = document.documentElement; 1128 documentIsHTML = !jQuery.isXMLDoc( document ); 1129 1130 // Support: iOS 7 only, IE 9 - 11+ 1131 // Older browsers didn't support unprefixed `matches`. 1132 matches = documentElement.matches || 1133 documentElement.webkitMatchesSelector || 1134 documentElement.msMatchesSelector; 1135 1136 // Support: IE 9 - 11+, Edge 12 - 18+ 1137 // Accessing iframe documents after unload throws "permission denied" errors 1138 // (see trac-13936). 1139 // Limit the fix to IE & Edge Legacy; despite Edge 15+ implementing `matches`, 1140 // all IE 9+ and Edge Legacy versions implement `msMatchesSelector` as well. 1141 if ( documentElement.msMatchesSelector && 1142 1143 // Support: IE 11+, Edge 17 - 18+ 1144 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing 1145 // two documents; shallow comparisons work. 1146 // eslint-disable-next-line eqeqeq 1147 preferredDoc != document && 1148 ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { 1149 1150 // Support: IE 9 - 11+, Edge 12 - 18+ 1151 subWindow.addEventListener( "unload", unloadHandler ); 1152 } 1153 1154 // Support: IE <10 1155 // Check if getElementById returns elements by name 1156 // The broken getElementById methods don't pick up programmatically-set names, 1157 // so use a roundabout getElementsByName test 1158 support.getById = assert( function( el ) { 1159 documentElement.appendChild( el ).id = jQuery.expando; 1160 return !document.getElementsByName || 1161 !document.getElementsByName( jQuery.expando ).length; 1162 } ); 1163 1164 // Support: IE 9 only 1165 // Check to see if it's possible to do matchesSelector 1166 // on a disconnected node. 1167 support.disconnectedMatch = assert( function( el ) { 1168 return matches.call( el, "*" ); 1169 } ); 1170 1171 // Support: IE 9 - 11+, Edge 12 - 18+ 1172 // IE/Edge don't support the :scope pseudo-class. 1173 support.scope = assert( function() { 1174 return document.querySelectorAll( ":scope" ); 1175 } ); 1176 1177 // Support: Chrome 105 - 111 only, Safari 15.4 - 16.3 only 1178 // Make sure the `:has()` argument is parsed unforgivingly. 1179 // We include `*` in the test to detect buggy implementations that are 1180 // _selectively_ forgiving (specifically when the list includes at least 1181 // one valid selector). 1182 // Note that we treat complete lack of support for `:has()` as if it were 1183 // spec-compliant support, which is fine because use of `:has()` in such 1184 // environments will fail in the qSA path and fall back to jQuery traversal 1185 // anyway. 1186 support.cssHas = assert( function() { 1187 try { 1188 document.querySelector( ":has(*,:jqfake)" ); 1189 return false; 1190 } catch ( e ) { 1191 return true; 1192 } 1193 } ); 1194 1195 // ID filter and find 1196 if ( support.getById ) { 1197 Expr.filter.ID = function( id ) { 1198 var attrId = id.replace( runescape, funescape ); 1199 return function( elem ) { 1200 return elem.getAttribute( "id" ) === attrId; 1201 }; 1202 }; 1203 Expr.find.ID = function( id, context ) { 1204 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { 1205 var elem = context.getElementById( id ); 1206 return elem ? [ elem ] : []; 1207 } 1208 }; 1209 } else { 1210 Expr.filter.ID = function( id ) { 1211 var attrId = id.replace( runescape, funescape ); 1212 return function( elem ) { 1213 var node = typeof elem.getAttributeNode !== "undefined" && 1214 elem.getAttributeNode( "id" ); 1215 return node && node.value === attrId; 1216 }; 1217 }; 1218 1219 // Support: IE 6 - 7 only 1220 // getElementById is not reliable as a find shortcut 1221 Expr.find.ID = function( id, context ) { 1222 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { 1223 var node, i, elems, 1224 elem = context.getElementById( id ); 1225 1226 if ( elem ) { 1227 1228 // Verify the id attribute 1229 node = elem.getAttributeNode( "id" ); 1230 if ( node && node.value === id ) { 1231 return [ elem ]; 1232 } 1233 1234 // Fall back on getElementsByName 1235 elems = context.getElementsByName( id ); 1236 i = 0; 1237 while ( ( elem = elems[ i++ ] ) ) { 1238 node = elem.getAttributeNode( "id" ); 1239 if ( node && node.value === id ) { 1240 return [ elem ]; 1241 } 1242 } 1243 } 1244 1245 return []; 1246 } 1247 }; 1248 } 1249 1250 // Tag 1251 Expr.find.TAG = function( tag, context ) { 1252 if ( typeof context.getElementsByTagName !== "undefined" ) { 1253 return context.getElementsByTagName( tag ); 1254 1255 // DocumentFragment nodes don't have gEBTN 1256 } else { 1257 return context.querySelectorAll( tag ); 1258 } 1259 }; 1260 1261 // Class 1262 Expr.find.CLASS = function( className, context ) { 1263 if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { 1264 return context.getElementsByClassName( className ); 1265 } 1266 }; 1267 1268 /* QSA/matchesSelector 1269 ---------------------------------------------------------------------- */ 1270 1271 // QSA and matchesSelector support 1272 1273 rbuggyQSA = []; 1274 1275 // Build QSA regex 1276 // Regex strategy adopted from Diego Perini 1277 assert( function( el ) { 1278 1279 var input; 1280 1281 documentElement.appendChild( el ).innerHTML = 1282 "<a id='" + expando + "' href='' disabled='disabled'></a>" + 1283 "<select id='" + expando + "-\r\\' disabled='disabled'>" + 1284 "<option selected=''></option></select>"; 1285 1286 // Support: iOS <=7 - 8 only 1287 // Boolean attributes and "value" are not treated correctly in some XML documents 1288 if ( !el.querySelectorAll( "[selected]" ).length ) { 1289 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); 1290 } 1291 1292 // Support: iOS <=7 - 8 only 1293 if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { 1294 rbuggyQSA.push( "~=" ); 1295 } 1296 1297 // Support: iOS 8 only 1298 // https://bugs.webkit.org/show_bug.cgi?id=136851 1299 // In-page `selector#id sibling-combinator selector` fails 1300 if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { 1301 rbuggyQSA.push( ".#.+[+~]" ); 1302 } 1303 1304 // Support: Chrome <=105+, Firefox <=104+, Safari <=15.4+ 1305 // In some of the document kinds, these selectors wouldn't work natively. 1306 // This is probably OK but for backwards compatibility we want to maintain 1307 // handling them through jQuery traversal in jQuery 3.x. 1308 if ( !el.querySelectorAll( ":checked" ).length ) { 1309 rbuggyQSA.push( ":checked" ); 1310 } 1311 1312 // Support: Windows 8 Native Apps 1313 // The type and name attributes are restricted during .innerHTML assignment 1314 input = document.createElement( "input" ); 1315 input.setAttribute( "type", "hidden" ); 1316 el.appendChild( input ).setAttribute( "name", "D" ); 1317 1318 // Support: IE 9 - 11+ 1319 // IE's :disabled selector does not pick up the children of disabled fieldsets 1320 // Support: Chrome <=105+, Firefox <=104+, Safari <=15.4+ 1321 // In some of the document kinds, these selectors wouldn't work natively. 1322 // This is probably OK but for backwards compatibility we want to maintain 1323 // handling them through jQuery traversal in jQuery 3.x. 1324 documentElement.appendChild( el ).disabled = true; 1325 if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { 1326 rbuggyQSA.push( ":enabled", ":disabled" ); 1327 } 1328 1329 // Support: IE 11+, Edge 15 - 18+ 1330 // IE 11/Edge don't find elements on a `[name='']` query in some cases. 1331 // Adding a temporary attribute to the document before the selection works 1332 // around the issue. 1333 // Interestingly, IE 10 & older don't seem to have the issue. 1334 input = document.createElement( "input" ); 1335 input.setAttribute( "name", "" ); 1336 el.appendChild( input ); 1337 if ( !el.querySelectorAll( "[name='']" ).length ) { 1338 rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + 1339 whitespace + "*(?:''|\"\")" ); 1340 } 1341 } ); 1342 1343 if ( !support.cssHas ) { 1344 1345 // Support: Chrome 105 - 110+, Safari 15.4 - 16.3+ 1346 // Our regular `try-catch` mechanism fails to detect natively-unsupported 1347 // pseudo-classes inside `:has()` (such as `:has(:contains("Foo"))`) 1348 // in browsers that parse the `:has()` argument as a forgiving selector list. 1349 // https://drafts.csswg.org/selectors/#relational now requires the argument 1350 // to be parsed unforgivingly, but browsers have not yet fully adjusted. 1351 rbuggyQSA.push( ":has" ); 1352 } 1353 1354 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); 1355 1356 /* Sorting 1357 ---------------------------------------------------------------------- */ 1358 1359 // Document order sorting 1360 sortOrder = function( a, b ) { 1361 1362 // Flag for duplicate removal 1363 if ( a === b ) { 1364 hasDuplicate = true; 1365 return 0; 1366 } 1367 1368 // Sort on method existence if only one input has compareDocumentPosition 1369 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; 1370 if ( compare ) { 1371 return compare; 1372 } 1373 1374 // Calculate position if both inputs belong to the same document 1375 // Support: IE 11+, Edge 17 - 18+ 1376 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing 1377 // two documents; shallow comparisons work. 1378 // eslint-disable-next-line eqeqeq 1379 compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? 1380 a.compareDocumentPosition( b ) : 1381 1382 // Otherwise we know they are disconnected 1383 1; 1384 1385 // Disconnected nodes 1386 if ( compare & 1 || 1387 ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { 1388 1389 // Choose the first element that is related to our preferred document 1390 // Support: IE 11+, Edge 17 - 18+ 1391 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing 1392 // two documents; shallow comparisons work. 1393 // eslint-disable-next-line eqeqeq 1394 if ( a === document || a.ownerDocument == preferredDoc && 1395 find.contains( preferredDoc, a ) ) { 1396 return -1; 1397 } 1398 1399 // Support: IE 11+, Edge 17 - 18+ 1400 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing 1401 // two documents; shallow comparisons work. 1402 // eslint-disable-next-line eqeqeq 1403 if ( b === document || b.ownerDocument == preferredDoc && 1404 find.contains( preferredDoc, b ) ) { 1405 return 1; 1406 } 1407 1408 // Maintain original order 1409 return sortInput ? 1410 ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : 1411 0; 1412 } 1413 1414 return compare & 4 ? -1 : 1; 1415 }; 1416 1417 return document; 1418} 1419 1420find.matches = function( expr, elements ) { 1421 return find( expr, null, null, elements ); 1422}; 1423 1424find.matchesSelector = function( elem, expr ) { 1425 setDocument( elem ); 1426 1427 if ( documentIsHTML && 1428 !nonnativeSelectorCache[ expr + " " ] && 1429 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { 1430 1431 try { 1432 var ret = matches.call( elem, expr ); 1433 1434 // IE 9's matchesSelector returns false on disconnected nodes 1435 if ( ret || support.disconnectedMatch || 1436 1437 // As well, disconnected nodes are said to be in a document 1438 // fragment in IE 9 1439 elem.document && elem.document.nodeType !== 11 ) { 1440 return ret; 1441 } 1442 } catch ( e ) { 1443 nonnativeSelectorCache( expr, true ); 1444 } 1445 } 1446 1447 return find( expr, document, null, [ elem ] ).length > 0; 1448}; 1449 1450find.contains = function( context, elem ) { 1451 1452 // Set document vars if needed 1453 // Support: IE 11+, Edge 17 - 18+ 1454 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing 1455 // two documents; shallow comparisons work. 1456 // eslint-disable-next-line eqeqeq 1457 if ( ( context.ownerDocument || context ) != document ) { 1458 setDocument( context ); 1459 } 1460 return jQuery.contains( context, elem ); 1461}; 1462 1463 1464find.attr = function( elem, name ) { 1465 1466 // Set document vars if needed 1467 // Support: IE 11+, Edge 17 - 18+ 1468 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing 1469 // two documents; shallow comparisons work. 1470 // eslint-disable-next-line eqeqeq 1471 if ( ( elem.ownerDocument || elem ) != document ) { 1472 setDocument( elem ); 1473 } 1474 1475 var fn = Expr.attrHandle[ name.toLowerCase() ], 1476 1477 // Don't get fooled by Object.prototype properties (see trac-13807) 1478 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? 1479 fn( elem, name, !documentIsHTML ) : 1480 undefined; 1481 1482 if ( val !== undefined ) { 1483 return val; 1484 } 1485 1486 return elem.getAttribute( name ); 1487}; 1488 1489find.error = function( msg ) { 1490 throw new Error( "Syntax error, unrecognized expression: " + msg ); 1491}; 1492 1493/** 1494 * Document sorting and removing duplicates 1495 * @param {ArrayLike} results 1496 */ 1497jQuery.uniqueSort = function( results ) { 1498 var elem, 1499 duplicates = [], 1500 j = 0, 1501 i = 0; 1502 1503 // Unless we *know* we can detect duplicates, assume their presence 1504 // 1505 // Support: Android <=4.0+ 1506 // Testing for detecting duplicates is unpredictable so instead assume we can't 1507 // depend on duplicate detection in all browsers without a stable sort. 1508 hasDuplicate = !support.sortStable; 1509 sortInput = !support.sortStable && slice.call( results, 0 ); 1510 sort.call( results, sortOrder ); 1511 1512 if ( hasDuplicate ) { 1513 while ( ( elem = results[ i++ ] ) ) { 1514 if ( elem === results[ i ] ) { 1515 j = duplicates.push( i ); 1516 } 1517 } 1518 while ( j-- ) { 1519 splice.call( results, duplicates[ j ], 1 ); 1520 } 1521 } 1522 1523 // Clear input after sorting to release objects 1524 // See https://github.com/jquery/sizzle/pull/225 1525 sortInput = null; 1526 1527 return results; 1528}; 1529 1530jQuery.fn.uniqueSort = function() { 1531 return this.pushStack( jQuery.uniqueSort( slice.apply( this ) ) ); 1532}; 1533 1534Expr = jQuery.expr = { 1535 1536 // Can be adjusted by the user 1537 cacheLength: 50, 1538 1539 createPseudo: markFunction, 1540 1541 match: matchExpr, 1542 1543 attrHandle: {}, 1544 1545 find: {}, 1546 1547 relative: { 1548 ">": { dir: "parentNode", first: true }, 1549 " ": { dir: "parentNode" }, 1550 "+": { dir: "previousSibling", first: true }, 1551 "~": { dir: "previousSibling" } 1552 }, 1553 1554 preFilter: { 1555 ATTR: function( match ) { 1556 match[ 1 ] = match[ 1 ].replace( runescape, funescape ); 1557 1558 // Move the given value to match[3] whether quoted or unquoted 1559 match[ 3 ] = ( match[ 3 ] || match[ 4 ] || match[ 5 ] || "" ) 1560 .replace( runescape, funescape ); 1561 1562 if ( match[ 2 ] === "~=" ) { 1563 match[ 3 ] = " " + match[ 3 ] + " "; 1564 } 1565 1566 return match.slice( 0, 4 ); 1567 }, 1568 1569 CHILD: function( match ) { 1570 1571 /* matches from matchExpr["CHILD"] 1572 1 type (only|nth|...) 1573 2 what (child|of-type) 1574 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 1575 4 xn-component of xn+y argument ([+-]?\d*n|) 1576 5 sign of xn-component 1577 6 x of xn-component 1578 7 sign of y-component 1579 8 y of y-component 1580 */ 1581 match[ 1 ] = match[ 1 ].toLowerCase(); 1582 1583 if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { 1584 1585 // nth-* requires argument 1586 if ( !match[ 3 ] ) { 1587 find.error( match[ 0 ] ); 1588 } 1589 1590 // numeric x and y parameters for Expr.filter.CHILD 1591 // remember that false/true cast respectively to 0/1 1592 match[ 4 ] = +( match[ 4 ] ? 1593 match[ 5 ] + ( match[ 6 ] || 1 ) : 1594 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) 1595 ); 1596 match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); 1597 1598 // other types prohibit arguments 1599 } else if ( match[ 3 ] ) { 1600 find.error( match[ 0 ] ); 1601 } 1602 1603 return match; 1604 }, 1605 1606 PSEUDO: function( match ) { 1607 var excess, 1608 unquoted = !match[ 6 ] && match[ 2 ]; 1609 1610 if ( matchExpr.CHILD.test( match[ 0 ] ) ) { 1611 return null; 1612 } 1613 1614 // Accept quoted arguments as-is 1615 if ( match[ 3 ] ) { 1616 match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; 1617 1618 // Strip excess characters from unquoted arguments 1619 } else if ( unquoted && rpseudo.test( unquoted ) && 1620 1621 // Get excess from tokenize (recursively) 1622 ( excess = tokenize( unquoted, true ) ) && 1623 1624 // advance to the next closing parenthesis 1625 ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { 1626 1627 // excess is a negative index 1628 match[ 0 ] = match[ 0 ].slice( 0, excess ); 1629 match[ 2 ] = unquoted.slice( 0, excess ); 1630 } 1631 1632 // Return only captures needed by the pseudo filter method (type and argument) 1633 return match.slice( 0, 3 ); 1634 } 1635 }, 1636 1637 filter: { 1638 1639 TAG: function( nodeNameSelector ) { 1640 var expectedNodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); 1641 return nodeNameSelector === "*" ? 1642 function() { 1643 return true; 1644 } : 1645 function( elem ) { 1646 return nodeName( elem, expectedNodeName ); 1647 }; 1648 }, 1649 1650 CLASS: function( className ) { 1651 var pattern = classCache[ className + " " ]; 1652 1653 return pattern || 1654 ( pattern = new RegExp( "(^|" + whitespace + ")" + className + 1655 "(" + whitespace + "|$)" ) ) && 1656 classCache( className, function( elem ) { 1657 return pattern.test( 1658 typeof elem.className === "string" && elem.className || 1659 typeof elem.getAttribute !== "undefined" && 1660 elem.getAttribute( "class" ) || 1661 "" 1662 ); 1663 } ); 1664 }, 1665 1666 ATTR: function( name, operator, check ) { 1667 return function( elem ) { 1668 var result = find.attr( elem, name ); 1669 1670 if ( result == null ) { 1671 return operator === "!="; 1672 } 1673 if ( !operator ) { 1674 return true; 1675 } 1676 1677 result += ""; 1678 1679 if ( operator === "=" ) { 1680 return result === check; 1681 } 1682 if ( operator === "!=" ) { 1683 return result !== check; 1684 } 1685 if ( operator === "^=" ) { 1686 return check && result.indexOf( check ) === 0; 1687 } 1688 if ( operator === "*=" ) { 1689 return check && result.indexOf( check ) > -1; 1690 } 1691 if ( operator === "$=" ) { 1692 return check && result.slice( -check.length ) === check; 1693 } 1694 if ( operator === "~=" ) { 1695 return ( " " + result.replace( rwhitespace, " " ) + " " ) 1696 .indexOf( check ) > -1; 1697 } 1698 if ( operator === "|=" ) { 1699 return result === check || result.slice( 0, check.length + 1 ) === check + "-"; 1700 } 1701 1702 return false; 1703 }; 1704 }, 1705 1706 CHILD: function( type, what, _argument, first, last ) { 1707 var simple = type.slice( 0, 3 ) !== "nth", 1708 forward = type.slice( -4 ) !== "last", 1709 ofType = what === "of-type"; 1710 1711 return first === 1 && last === 0 ? 1712 1713 // Shortcut for :nth-*(n) 1714 function( elem ) { 1715 return !!elem.parentNode; 1716 } : 1717 1718 function( elem, _context, xml ) { 1719 var cache, outerCache, node, nodeIndex, start, 1720 dir = simple !== forward ? "nextSibling" : "previousSibling", 1721 parent = elem.parentNode, 1722 name = ofType && elem.nodeName.toLowerCase(), 1723 useCache = !xml && !ofType, 1724 diff = false; 1725 1726 if ( parent ) { 1727 1728 // :(first|last|only)-(child|of-type) 1729 if ( simple ) { 1730 while ( dir ) { 1731 node = elem; 1732 while ( ( node = node[ dir ] ) ) { 1733 if ( ofType ? 1734 nodeName( node, name ) : 1735 node.nodeType === 1 ) { 1736 1737 return false; 1738 } 1739 } 1740 1741 // Reverse direction for :only-* (if we haven't yet done so) 1742 start = dir = type === "only" && !start && "nextSibling"; 1743 } 1744 return true; 1745 } 1746 1747 start = [ forward ? parent.firstChild : parent.lastChild ]; 1748 1749 // non-xml :nth-child(...) stores cache data on `parent` 1750 if ( forward && useCache ) { 1751 1752 // Seek `elem` from a previously-cached index 1753 outerCache = parent[ expando ] || ( parent[ expando ] = {} ); 1754 cache = outerCache[ type ] || []; 1755 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; 1756 diff = nodeIndex && cache[ 2 ]; 1757 node = nodeIndex && parent.childNodes[ nodeIndex ]; 1758 1759 while ( ( node = ++nodeIndex && node && node[ dir ] || 1760 1761 // Fallback to seeking `elem` from the start 1762 ( diff = nodeIndex = 0 ) || start.pop() ) ) { 1763 1764 // When found, cache indexes on `parent` and break 1765 if ( node.nodeType === 1 && ++diff && node === elem ) { 1766 outerCache[ type ] = [ dirruns, nodeIndex, diff ]; 1767 break; 1768 } 1769 } 1770 1771 } else { 1772 1773 // Use previously-cached element index if available 1774 if ( useCache ) { 1775 outerCache = elem[ expando ] || ( elem[ expando ] = {} ); 1776 cache = outerCache[ type ] || []; 1777 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; 1778 diff = nodeIndex; 1779 } 1780 1781 // xml :nth-child(...) 1782 // or :nth-last-child(...) or :nth(-last)?-of-type(...) 1783 if ( diff === false ) { 1784 1785 // Use the same loop as above to seek `elem` from the start 1786 while ( ( node = ++nodeIndex && node && node[ dir ] || 1787 ( diff = nodeIndex = 0 ) || start.pop() ) ) { 1788 1789 if ( ( ofType ? 1790 nodeName( node, name ) : 1791 node.nodeType === 1 ) && 1792 ++diff ) { 1793 1794 // Cache the index of each encountered element 1795 if ( useCache ) { 1796 outerCache = node[ expando ] || 1797 ( node[ expando ] = {} ); 1798 outerCache[ type ] = [ dirruns, diff ]; 1799 } 1800 1801 if ( node === elem ) { 1802 break; 1803 } 1804 } 1805 } 1806 } 1807 } 1808 1809 // Incorporate the offset, then check against cycle size 1810 diff -= last; 1811 return diff === first || ( diff % first === 0 && diff / first >= 0 ); 1812 } 1813 }; 1814 }, 1815 1816 PSEUDO: function( pseudo, argument ) { 1817 1818 // pseudo-class names are case-insensitive 1819 // https://www.w3.org/TR/selectors/#pseudo-classes 1820 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters 1821 // Remember that setFilters inherits from pseudos 1822 var args, 1823 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || 1824 find.error( "unsupported pseudo: " + pseudo ); 1825 1826 // The user may use createPseudo to indicate that 1827 // arguments are needed to create the filter function 1828 // just as jQuery does 1829 if ( fn[ expando ] ) { 1830 return fn( argument ); 1831 } 1832 1833 // But maintain support for old signatures 1834 if ( fn.length > 1 ) { 1835 args = [ pseudo, pseudo, "", argument ]; 1836 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? 1837 markFunction( function( seed, matches ) { 1838 var idx, 1839 matched = fn( seed, argument ), 1840 i = matched.length; 1841 while ( i-- ) { 1842 idx = indexOf.call( seed, matched[ i ] ); 1843 seed[ idx ] = !( matches[ idx ] = matched[ i ] ); 1844 } 1845 } ) : 1846 function( elem ) { 1847 return fn( elem, 0, args ); 1848 }; 1849 } 1850 1851 return fn; 1852 } 1853 }, 1854 1855 pseudos: { 1856 1857 // Potentially complex pseudos 1858 not: markFunction( function( selector ) { 1859 1860 // Trim the selector passed to compile 1861 // to avoid treating leading and trailing 1862 // spaces as combinators 1863 var input = [], 1864 results = [], 1865 matcher = compile( selector.replace( rtrimCSS, "$1" ) ); 1866 1867 return matcher[ expando ] ? 1868 markFunction( function( seed, matches, _context, xml ) { 1869 var elem, 1870 unmatched = matcher( seed, null, xml, [] ), 1871 i = seed.length; 1872 1873 // Match elements unmatched by `matcher` 1874 while ( i-- ) { 1875 if ( ( elem = unmatched[ i ] ) ) { 1876 seed[ i ] = !( matches[ i ] = elem ); 1877 } 1878 } 1879 } ) : 1880 function( elem, _context, xml ) { 1881 input[ 0 ] = elem; 1882 matcher( input, null, xml, results ); 1883 1884 // Don't keep the element 1885 // (see https://github.com/jquery/sizzle/issues/299) 1886 input[ 0 ] = null; 1887 return !results.pop(); 1888 }; 1889 } ), 1890 1891 has: markFunction( function( selector ) { 1892 return function( elem ) { 1893 return find( selector, elem ).length > 0; 1894 }; 1895 } ), 1896 1897 contains: markFunction( function( text ) { 1898 text = text.replace( runescape, funescape ); 1899 return function( elem ) { 1900 return ( elem.textContent || jQuery.text( elem ) ).indexOf( text ) > -1; 1901 }; 1902 } ), 1903 1904 // "Whether an element is represented by a :lang() selector 1905 // is based solely on the element's language value 1906 // being equal to the identifier C, 1907 // or beginning with the identifier C immediately followed by "-". 1908 // The matching of C against the element's language value is performed case-insensitively. 1909 // The identifier C does not have to be a valid language name." 1910 // https://www.w3.org/TR/selectors/#lang-pseudo 1911 lang: markFunction( function( lang ) { 1912 1913 // lang value must be a valid identifier 1914 if ( !ridentifier.test( lang || "" ) ) { 1915 find.error( "unsupported lang: " + lang ); 1916 } 1917 lang = lang.replace( runescape, funescape ).toLowerCase(); 1918 return function( elem ) { 1919 var elemLang; 1920 do { 1921 if ( ( elemLang = documentIsHTML ? 1922 elem.lang : 1923 elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { 1924 1925 elemLang = elemLang.toLowerCase(); 1926 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; 1927 } 1928 } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); 1929 return false; 1930 }; 1931 } ), 1932 1933 // Miscellaneous 1934 target: function( elem ) { 1935 var hash = window.location && window.location.hash; 1936 return hash && hash.slice( 1 ) === elem.id; 1937 }, 1938 1939 root: function( elem ) { 1940 return elem === documentElement; 1941 }, 1942 1943 focus: function( elem ) { 1944 return elem === safeActiveElement() && 1945 document.hasFocus() && 1946 !!( elem.type || elem.href || ~elem.tabIndex ); 1947 }, 1948 1949 // Boolean properties 1950 enabled: createDisabledPseudo( false ), 1951 disabled: createDisabledPseudo( true ), 1952 1953 checked: function( elem ) { 1954 1955 // In CSS3, :checked should return both checked and selected elements 1956 // https://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked 1957 return ( nodeName( elem, "input" ) && !!elem.checked ) || 1958 ( nodeName( elem, "option" ) && !!elem.selected ); 1959 }, 1960 1961 selected: function( elem ) { 1962 1963 // Support: IE <=11+ 1964 // Accessing the selectedIndex property 1965 // forces the browser to treat the default option as 1966 // selected when in an optgroup. 1967 if ( elem.parentNode ) { 1968 // eslint-disable-next-line no-unused-expressions 1969 elem.parentNode.selectedIndex; 1970 } 1971 1972 return elem.selected === true; 1973 }, 1974 1975 // Contents 1976 empty: function( elem ) { 1977 1978 // https://www.w3.org/TR/selectors/#empty-pseudo 1979 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), 1980 // but not by others (comment: 8; processing instruction: 7; etc.) 1981 // nodeType < 6 works because attributes (2) do not appear as children 1982 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { 1983 if ( elem.nodeType < 6 ) { 1984 return false; 1985 } 1986 } 1987 return true; 1988 }, 1989 1990 parent: function( elem ) { 1991 return !Expr.pseudos.empty( elem ); 1992 }, 1993 1994 // Element/input types 1995 header: function( elem ) { 1996 return rheader.test( elem.nodeName ); 1997 }, 1998 1999 input: function( elem ) { 2000 return rinputs.test( elem.nodeName ); 2001 }, 2002 2003 button: function( elem ) { 2004 return nodeName( elem, "input" ) && elem.type === "button" || 2005 nodeName( elem, "button" ); 2006 }, 2007 2008 text: function( elem ) { 2009 var attr; 2010 return nodeName( elem, "input" ) && elem.type === "text" && 2011 2012 // Support: IE <10 only 2013 // New HTML5 attribute values (e.g., "search") appear 2014 // with elem.type === "text" 2015 ( ( attr = elem.getAttribute( "type" ) ) == null || 2016 attr.toLowerCase() === "text" ); 2017 }, 2018 2019 // Position-in-collection 2020 first: createPositionalPseudo( function() { 2021 return [ 0 ]; 2022 } ), 2023 2024 last: createPositionalPseudo( function( _matchIndexes, length ) { 2025 return [ length - 1 ]; 2026 } ), 2027 2028 eq: createPositionalPseudo( function( _matchIndexes, length, argument ) { 2029 return [ argument < 0 ? argument + length : argument ]; 2030 } ), 2031 2032 even: createPositionalPseudo( function( matchIndexes, length ) { 2033 var i = 0; 2034 for ( ; i < length; i += 2 ) { 2035 matchIndexes.push( i ); 2036 } 2037 return matchIndexes; 2038 } ), 2039 2040 odd: createPositionalPseudo( function( matchIndexes, length ) { 2041 var i = 1; 2042 for ( ; i < length; i += 2 ) { 2043 matchIndexes.push( i ); 2044 } 2045 return matchIndexes; 2046 } ), 2047 2048 lt: createPositionalPseudo( function( matchIndexes, length, argument ) { 2049 var i; 2050 2051 if ( argument < 0 ) { 2052 i = argument + length; 2053 } else if ( argument > length ) { 2054 i = length; 2055 } else { 2056 i = argument; 2057 } 2058 2059 for ( ; --i >= 0; ) { 2060 matchIndexes.push( i ); 2061 } 2062 return matchIndexes; 2063 } ), 2064 2065 gt: createPositionalPseudo( function( matchIndexes, length, argument ) { 2066 var i = argument < 0 ? argument + length : argument; 2067 for ( ; ++i < length; ) { 2068 matchIndexes.push( i ); 2069 } 2070 return matchIndexes; 2071 } ) 2072 } 2073}; 2074 2075Expr.pseudos.nth = Expr.pseudos.eq; 2076 2077// Add button/input type pseudos 2078for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { 2079 Expr.pseudos[ i ] = createInputPseudo( i ); 2080} 2081for ( i in { submit: true, reset: true } ) { 2082 Expr.pseudos[ i ] = createButtonPseudo( i ); 2083} 2084 2085// Easy API for creating new setFilters 2086function setFilters() {} 2087setFilters.prototype = Expr.filters = Expr.pseudos; 2088Expr.setFilters = new setFilters(); 2089 2090function tokenize( selector, parseOnly ) { 2091 var matched, match, tokens, type, 2092 soFar, groups, preFilters, 2093 cached = tokenCache[ selector + " " ]; 2094 2095 if ( cached ) { 2096 return parseOnly ? 0 : cached.slice( 0 ); 2097 } 2098 2099 soFar = selector; 2100 groups = []; 2101 preFilters = Expr.preFilter; 2102 2103 while ( soFar ) { 2104 2105 // Comma and first run 2106 if ( !matched || ( match = rcomma.exec( soFar ) ) ) { 2107 if ( match ) { 2108 2109 // Don't consume trailing commas as valid 2110 soFar = soFar.slice( match[ 0 ].length ) || soFar; 2111 } 2112 groups.push( ( tokens = [] ) ); 2113 } 2114 2115 matched = false; 2116 2117 // Combinators 2118 if ( ( match = rleadingCombinator.exec( soFar ) ) ) { 2119 matched = match.shift(); 2120 tokens.push( { 2121 value: matched, 2122 2123 // Cast descendant combinators to space 2124 type: match[ 0 ].replace( rtrimCSS, " " ) 2125 } ); 2126 soFar = soFar.slice( matched.length ); 2127 } 2128 2129 // Filters 2130 for ( type in Expr.filter ) { 2131 if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || 2132 ( match = preFilters[ type ]( match ) ) ) ) { 2133 matched = match.shift(); 2134 tokens.push( { 2135 value: matched, 2136 type: type, 2137 matches: match 2138 } ); 2139 soFar = soFar.slice( matched.length ); 2140 } 2141 } 2142 2143 if ( !matched ) { 2144 break; 2145 } 2146 } 2147 2148 // Return the length of the invalid excess 2149 // if we're just parsing 2150 // Otherwise, throw an error or return tokens 2151 if ( parseOnly ) { 2152 return soFar.length; 2153 } 2154 2155 return soFar ? 2156 find.error( selector ) : 2157 2158 // Cache the tokens 2159 tokenCache( selector, groups ).slice( 0 ); 2160} 2161 2162function toSelector( tokens ) { 2163 var i = 0, 2164 len = tokens.length, 2165 selector = ""; 2166 for ( ; i < len; i++ ) { 2167 selector += tokens[ i ].value; 2168 } 2169 return selector; 2170} 2171 2172function addCombinator( matcher, combinator, base ) { 2173 var dir = combinator.dir, 2174 skip = combinator.next, 2175 key = skip || dir, 2176 checkNonElements = base && key === "parentNode", 2177 doneName = done++; 2178 2179 return combinator.first ? 2180 2181 // Check against closest ancestor/preceding element 2182 function( elem, context, xml ) { 2183 while ( ( elem = elem[ dir ] ) ) { 2184 if ( elem.nodeType === 1 || checkNonElements ) { 2185 return matcher( elem, context, xml ); 2186 } 2187 } 2188 return false; 2189 } : 2190 2191 // Check against all ancestor/preceding elements 2192 function( elem, context, xml ) { 2193 var oldCache, outerCache, 2194 newCache = [ dirruns, doneName ]; 2195 2196 // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching 2197 if ( xml ) { 2198 while ( ( elem = elem[ dir ] ) ) { 2199 if ( elem.nodeType === 1 || checkNonElements ) { 2200 if ( matcher( elem, context, xml ) ) { 2201 return true; 2202 } 2203 } 2204 } 2205 } else { 2206 while ( ( elem = elem[ dir ] ) ) { 2207 if ( elem.nodeType === 1 || checkNonElements ) { 2208 outerCache = elem[ expando ] || ( elem[ expando ] = {} ); 2209 2210 if ( skip && nodeName( elem, skip ) ) { 2211 elem = elem[ dir ] || elem; 2212 } else if ( ( oldCache = outerCache[ key ] ) && 2213 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { 2214 2215 // Assign to newCache so results back-propagate to previous elements 2216 return ( newCache[ 2 ] = oldCache[ 2 ] ); 2217 } else { 2218 2219 // Reuse newcache so results back-propagate to previous elements 2220 outerCache[ key ] = newCache; 2221 2222 // A match means we're done; a fail means we have to keep checking 2223 if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { 2224 return true; 2225 } 2226 } 2227 } 2228 } 2229 } 2230 return false; 2231 }; 2232} 2233 2234function elementMatcher( matchers ) { 2235 return matchers.length > 1 ? 2236 function( elem, context, xml ) { 2237 var i = matchers.length; 2238 while ( i-- ) { 2239 if ( !matchers[ i ]( elem, context, xml ) ) { 2240 return false; 2241 } 2242 } 2243 return true; 2244 } : 2245 matchers[ 0 ]; 2246} 2247 2248function multipleContexts( selector, contexts, results ) { 2249 var i = 0, 2250 len = contexts.length; 2251 for ( ; i < len; i++ ) { 2252 find( selector, contexts[ i ], results ); 2253 } 2254 return results; 2255} 2256 2257function condense( unmatched, map, filter, context, xml ) { 2258 var elem, 2259 newUnmatched = [], 2260 i = 0, 2261 len = unmatched.length, 2262 mapped = map != null; 2263 2264 for ( ; i < len; i++ ) { 2265 if ( ( elem = unmatched[ i ] ) ) { 2266 if ( !filter || filter( elem, context, xml ) ) { 2267 newUnmatched.push( elem ); 2268 if ( mapped ) { 2269 map.push( i ); 2270 } 2271 } 2272 } 2273 } 2274 2275 return newUnmatched; 2276} 2277 2278function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { 2279 if ( postFilter && !postFilter[ expando ] ) { 2280 postFilter = setMatcher( postFilter ); 2281 } 2282 if ( postFinder && !postFinder[ expando ] ) { 2283 postFinder = setMatcher( postFinder, postSelector ); 2284 } 2285 return markFunction( function( seed, results, context, xml ) { 2286 var temp, i, elem, matcherOut, 2287 preMap = [], 2288 postMap = [], 2289 preexisting = results.length, 2290 2291 // Get initial elements from seed or context 2292 elems = seed || 2293 multipleContexts( selector || "*", 2294 context.nodeType ? [ context ] : context, [] ), 2295 2296 // Prefilter to get matcher input, preserving a map for seed-results synchronization 2297 matcherIn = preFilter && ( seed || !selector ) ? 2298 condense( elems, preMap, preFilter, context, xml ) : 2299 elems; 2300 2301 if ( matcher ) { 2302 2303 // If we have a postFinder, or filtered seed, or non-seed postFilter 2304 // or preexisting results, 2305 matcherOut = postFinder || ( seed ? preFilter : preexisting || postFilter ) ? 2306 2307 // ...intermediate processing is necessary 2308 [] : 2309 2310 // ...otherwise use results directly 2311 results; 2312 2313 // Find primary matches 2314 matcher( matcherIn, matcherOut, context, xml ); 2315 } else { 2316 matcherOut = matcherIn; 2317 } 2318 2319 // Apply postFilter 2320 if ( postFilter ) { 2321 temp = condense( matcherOut, postMap ); 2322 postFilter( temp, [], context, xml ); 2323 2324 // Un-match failing elements by moving them back to matcherIn 2325 i = temp.length; 2326 while ( i-- ) { 2327 if ( ( elem = temp[ i ] ) ) { 2328 matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); 2329 } 2330 } 2331 } 2332 2333 if ( seed ) { 2334 if ( postFinder || preFilter ) { 2335 if ( postFinder ) { 2336 2337 // Get the final matcherOut by condensing this intermediate into postFinder contexts 2338 temp = []; 2339 i = matcherOut.length; 2340 while ( i-- ) { 2341 if ( ( elem = matcherOut[ i ] ) ) { 2342 2343 // Restore matcherIn since elem is not yet a final match 2344 temp.push( ( matcherIn[ i ] = elem ) ); 2345 } 2346 } 2347 postFinder( null, ( matcherOut = [] ), temp, xml ); 2348 } 2349 2350 // Move matched elements from seed to results to keep them synchronized 2351 i = matcherOut.length; 2352 while ( i-- ) { 2353 if ( ( elem = matcherOut[ i ] ) && 2354 ( temp = postFinder ? indexOf.call( seed, elem ) : preMap[ i ] ) > -1 ) { 2355 2356 seed[ temp ] = !( results[ temp ] = elem ); 2357 } 2358 } 2359 } 2360 2361 // Add elements to results, through postFinder if defined 2362 } else { 2363 matcherOut = condense( 2364 matcherOut === results ? 2365 matcherOut.splice( preexisting, matcherOut.length ) : 2366 matcherOut 2367 ); 2368 if ( postFinder ) { 2369 postFinder( null, results, matcherOut, xml ); 2370 } else { 2371 push.apply( results, matcherOut ); 2372 } 2373 } 2374 } ); 2375} 2376 2377function matcherFromTokens( tokens ) { 2378 var checkContext, matcher, j, 2379 len = tokens.length, 2380 leadingRelative = Expr.relative[ tokens[ 0 ].type ], 2381 implicitRelative = leadingRelative || Expr.relative[ " " ], 2382 i = leadingRelative ? 1 : 0, 2383 2384 // The foundational matcher ensures that elements are reachable from top-level context(s) 2385 matchContext = addCombinator( function( elem ) { 2386 return elem === checkContext; 2387 }, implicitRelative, true ), 2388 matchAnyContext = addCombinator( function( elem ) { 2389 return indexOf.call( checkContext, elem ) > -1; 2390 }, implicitRelative, true ), 2391 matchers = [ function( elem, context, xml ) { 2392 2393 // Support: IE 11+, Edge 17 - 18+ 2394 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing 2395 // two documents; shallow comparisons work. 2396 // eslint-disable-next-line eqeqeq 2397 var ret = ( !leadingRelative && ( xml || context != outermostContext ) ) || ( 2398 ( checkContext = context ).nodeType ? 2399 matchContext( elem, context, xml ) : 2400 matchAnyContext( elem, context, xml ) ); 2401 2402 // Avoid hanging onto element 2403 // (see https://github.com/jquery/sizzle/issues/299) 2404 checkContext = null; 2405 return ret; 2406 } ]; 2407 2408 for ( ; i < len; i++ ) { 2409 if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { 2410 matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; 2411 } else { 2412 matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); 2413 2414 // Return special upon seeing a positional matcher 2415 if ( matcher[ expando ] ) { 2416 2417 // Find the next relative operator (if any) for proper handling 2418 j = ++i; 2419 for ( ; j < len; j++ ) { 2420 if ( Expr.relative[ tokens[ j ].type ] ) { 2421 break; 2422 } 2423 } 2424 return setMatcher( 2425 i > 1 && elementMatcher( matchers ), 2426 i > 1 && toSelector( 2427 2428 // If the preceding token was a descendant combinator, insert an implicit any-element `*` 2429 tokens.slice( 0, i - 1 ) 2430 .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) 2431 ).replace( rtrimCSS, "$1" ), 2432 matcher, 2433 i < j && matcherFromTokens( tokens.slice( i, j ) ), 2434 j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), 2435 j < len && toSelector( tokens ) 2436 ); 2437 } 2438 matchers.push( matcher ); 2439 } 2440 } 2441 2442 return elementMatcher( matchers ); 2443} 2444 2445function matcherFromGroupMatchers( elementMatchers, setMatchers ) { 2446 var bySet = setMatchers.length > 0, 2447 byElement = elementMatchers.length > 0, 2448 superMatcher = function( seed, context, xml, results, outermost ) { 2449 var elem, j, matcher, 2450 matchedCount = 0, 2451 i = "0", 2452 unmatched = seed && [], 2453 setMatched = [], 2454 contextBackup = outermostContext, 2455 2456 // We must always have either seed elements or outermost context 2457 elems = seed || byElement && Expr.find.TAG( "*", outermost ), 2458 2459 // Use integer dirruns iff this is the outermost matcher 2460 dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), 2461 len = elems.length; 2462 2463 if ( outermost ) { 2464 2465 // Support: IE 11+, Edge 17 - 18+ 2466 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing 2467 // two documents; shallow comparisons work. 2468 // eslint-disable-next-line eqeqeq 2469 outermostContext = context == document || context || outermost; 2470 } 2471 2472 // Add elements passing elementMatchers directly to results 2473 // Support: iOS <=7 - 9 only 2474 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching 2475 // elements by id. (see trac-14142) 2476 for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { 2477 if ( byElement && elem ) { 2478 j = 0; 2479 2480 // Support: IE 11+, Edge 17 - 18+ 2481 // IE/Edge sometimes throw a "Permission denied" error when strict-comparing 2482 // two documents; shallow comparisons work. 2483 // eslint-disable-next-line eqeqeq 2484 if ( !context && elem.ownerDocument != document ) { 2485 setDocument( elem ); 2486 xml = !documentIsHTML; 2487 } 2488 while ( ( matcher = elementMatchers[ j++ ] ) ) { 2489 if ( matcher( elem, context || document, xml ) ) { 2490 push.call( results, elem ); 2491 break; 2492 } 2493 } 2494 if ( outermost ) { 2495 dirruns = dirrunsUnique; 2496 } 2497 } 2498 2499 // Track unmatched elements for set filters 2500 if ( bySet ) { 2501 2502 // They will have gone through all possible matchers 2503 if ( ( elem = !matcher && elem ) ) { 2504 matchedCount--; 2505 } 2506 2507 // Lengthen the array for every element, matched or not 2508 if ( seed ) { 2509 unmatched.push( elem ); 2510 } 2511 } 2512 } 2513 2514 // `i` is now the count of elements visited above, and adding it to `matchedCount` 2515 // makes the latter nonnegative. 2516 matchedCount += i; 2517 2518 // Apply set filters to unmatched elements 2519 // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` 2520 // equals `i`), unless we didn't visit _any_ elements in the above loop because we have 2521 // no element matchers and no seed. 2522 // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that 2523 // case, which will result in a "00" `matchedCount` that differs from `i` but is also 2524 // numerically zero. 2525 if ( bySet && i !== matchedCount ) { 2526 j = 0; 2527 while ( ( matcher = setMatchers[ j++ ] ) ) { 2528 matcher( unmatched, setMatched, context, xml ); 2529 } 2530 2531 if ( seed ) { 2532 2533 // Reintegrate element matches to eliminate the need for sorting 2534 if ( matchedCount > 0 ) { 2535 while ( i-- ) { 2536 if ( !( unmatched[ i ] || setMatched[ i ] ) ) { 2537 setMatched[ i ] = pop.call( results ); 2538 } 2539 } 2540 } 2541 2542 // Discard index placeholder values to get only actual matches 2543 setMatched = condense( setMatched ); 2544 } 2545 2546 // Add matches to results 2547 push.apply( results, setMatched ); 2548 2549 // Seedless set matches succeeding multiple successful matchers stipulate sorting 2550 if ( outermost && !seed && setMatched.length > 0 && 2551 ( matchedCount + setMatchers.length ) > 1 ) { 2552 2553 jQuery.uniqueSort( results ); 2554 } 2555 } 2556 2557 // Override manipulation of globals by nested matchers 2558 if ( outermost ) { 2559 dirruns = dirrunsUnique; 2560 outermostContext = contextBackup; 2561 } 2562 2563 return unmatched; 2564 }; 2565 2566 return bySet ? 2567 markFunction( superMatcher ) : 2568 superMatcher; 2569} 2570 2571function compile( selector, match /* Internal Use Only */ ) { 2572 var i, 2573 setMatchers = [], 2574 elementMatchers = [], 2575 cached = compilerCache[ selector + " " ]; 2576 2577 if ( !cached ) { 2578 2579 // Generate a function of recursive functions that can be used to check each element 2580 if ( !match ) { 2581 match = tokenize( selector ); 2582 } 2583 i = match.length; 2584 while ( i-- ) { 2585 cached = matcherFromTokens( match[ i ] ); 2586 if ( cached[ expando ] ) { 2587 setMatchers.push( cached ); 2588 } else { 2589 elementMatchers.push( cached ); 2590 } 2591 } 2592 2593 // Cache the compiled function 2594 cached = compilerCache( selector, 2595 matcherFromGroupMatchers( elementMatchers, setMatchers ) ); 2596 2597 // Save selector and tokenization 2598 cached.selector = selector; 2599 } 2600 return cached; 2601} 2602 2603/** 2604 * A low-level selection function that works with jQuery's compiled 2605 * selector functions 2606 * @param {String|Function} selector A selector or a pre-compiled 2607 * selector function built with jQuery selector compile 2608 * @param {Element} context 2609 * @param {Array} [results] 2610 * @param {Array} [seed] A set of elements to match against 2611 */ 2612function select( selector, context, results, seed ) { 2613 var i, tokens, token, type, find, 2614 compiled = typeof selector === "function" && selector, 2615 match = !seed && tokenize( ( selector = compiled.selector || selector ) ); 2616 2617 results = results || []; 2618 2619 // Try to minimize operations if there is only one selector in the list and no seed 2620 // (the latter of which guarantees us context) 2621 if ( match.length === 1 ) { 2622 2623 // Reduce context if the leading compound selector is an ID 2624 tokens = match[ 0 ] = match[ 0 ].slice( 0 ); 2625 if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && 2626 context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { 2627 2628 context = ( Expr.find.ID( 2629 token.matches[ 0 ].replace( runescape, funescape ), 2630 context 2631 ) || [] )[ 0 ]; 2632 if ( !context ) { 2633 return results; 2634 2635 // Precompiled matchers will still verify ancestry, so step up a level 2636 } else if ( compiled ) { 2637 context = context.parentNode; 2638 } 2639 2640 selector = selector.slice( tokens.shift().value.length ); 2641 } 2642 2643 // Fetch a seed set for right-to-left matching 2644 i = matchExpr.needsContext.test( selector ) ? 0 : tokens.length; 2645 while ( i-- ) { 2646 token = tokens[ i ]; 2647 2648 // Abort if we hit a combinator 2649 if ( Expr.relative[ ( type = token.type ) ] ) { 2650 break; 2651 } 2652 if ( ( find = Expr.find[ type ] ) ) { 2653 2654 // Search, expanding context for leading sibling combinators 2655 if ( ( seed = find( 2656 token.matches[ 0 ].replace( runescape, funescape ), 2657 rsibling.test( tokens[ 0 ].type ) && 2658 testContext( context.parentNode ) || context 2659 ) ) ) { 2660 2661 // If seed is empty or no tokens remain, we can return early 2662 tokens.splice( i, 1 ); 2663 selector = seed.length && toSelector( tokens ); 2664 if ( !selector ) { 2665 push.apply( results, seed ); 2666 return results; 2667 } 2668 2669 break; 2670 } 2671 } 2672 } 2673 } 2674 2675 // Compile and execute a filtering function if one is not provided 2676 // Provide `match` to avoid retokenization if we modified the selector above 2677 ( compiled || compile( selector, match ) )( 2678 seed, 2679 context, 2680 !documentIsHTML, 2681 results, 2682 !context || rsibling.test( selector ) && testContext( context.parentNode ) || context 2683 ); 2684 return results; 2685} 2686 2687// One-time assignments 2688 2689// Support: Android <=4.0 - 4.1+ 2690// Sort stability 2691support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; 2692 2693// Initialize against the default document 2694setDocument(); 2695 2696// Support: Android <=4.0 - 4.1+ 2697// Detached nodes confoundingly follow *each other* 2698support.sortDetached = assert( function( el ) { 2699 2700 // Should return 1, but returns 4 (following) 2701 return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; 2702} ); 2703 2704jQuery.find = find; 2705 2706// Deprecated 2707jQuery.expr[ ":" ] = jQuery.expr.pseudos; 2708jQuery.unique = jQuery.uniqueSort; 2709 2710// These have always been private, but they used to be documented as part of 2711// Sizzle so let's maintain them for now for backwards compatibility purposes. 2712find.compile = compile; 2713find.select = select; 2714find.setDocument = setDocument; 2715find.tokenize = tokenize; 2716 2717find.escape = jQuery.escapeSelector; 2718find.getText = jQuery.text; 2719find.isXML = jQuery.isXMLDoc; 2720find.selectors = jQuery.expr; 2721find.support = jQuery.support; 2722find.uniqueSort = jQuery.uniqueSort; 2723 2724 /* eslint-enable */ 2725 2726} )(); 2727 2728 2729var dir = function( elem, dir, until ) { 2730 var matched = [], 2731 truncate = until !== undefined; 2732 2733 while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { 2734 if ( elem.nodeType === 1 ) { 2735 if ( truncate && jQuery( elem ).is( until ) ) { 2736 break; 2737 } 2738 matched.push( elem ); 2739 } 2740 } 2741 return matched; 2742}; 2743 2744 2745var siblings = function( n, elem ) { 2746 var matched = []; 2747 2748 for ( ; n; n = n.nextSibling ) { 2749 if ( n.nodeType === 1 && n !== elem ) { 2750 matched.push( n ); 2751 } 2752 } 2753 2754 return matched; 2755}; 2756 2757 2758var rneedsContext = jQuery.expr.match.needsContext; 2759 2760var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); 2761 2762 2763 2764// Implement the identical functionality for filter and not 2765function winnow( elements, qualifier, not ) { 2766 if ( isFunction( qualifier ) ) { 2767 return jQuery.grep( elements, function( elem, i ) { 2768 return !!qualifier.call( elem, i, elem ) !== not; 2769 } ); 2770 } 2771 2772 // Single element 2773 if ( qualifier.nodeType ) { 2774 return jQuery.grep( elements, function( elem ) { 2775 return ( elem === qualifier ) !== not; 2776 } ); 2777 } 2778 2779 // Arraylike of elements (jQuery, arguments, Array) 2780 if ( typeof qualifier !== "string" ) { 2781 return jQuery.grep( elements, function( elem ) { 2782 return ( indexOf.call( qualifier, elem ) > -1 ) !== not; 2783 } ); 2784 } 2785 2786 // Filtered directly for both simple and complex selectors 2787 return jQuery.filter( qualifier, elements, not ); 2788} 2789 2790jQuery.filter = function( expr, elems, not ) { 2791 var elem = elems[ 0 ]; 2792 2793 if ( not ) { 2794 expr = ":not(" + expr + ")"; 2795 } 2796 2797 if ( elems.length === 1 && elem.nodeType === 1 ) { 2798 return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; 2799 } 2800 2801 return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { 2802 return elem.nodeType === 1; 2803 } ) ); 2804}; 2805 2806jQuery.fn.extend( { 2807 find: function( selector ) { 2808 var i, ret, 2809 len = this.length, 2810 self = this; 2811 2812 if ( typeof selector !== "string" ) { 2813 return this.pushStack( jQuery( selector ).filter( function() { 2814 for ( i = 0; i < len; i++ ) { 2815 if ( jQuery.contains( self[ i ], this ) ) { 2816 return true; 2817 } 2818 } 2819 } ) ); 2820 } 2821 2822 ret = this.pushStack( [] ); 2823 2824 for ( i = 0; i < len; i++ ) { 2825 jQuery.find( selector, self[ i ], ret ); 2826 } 2827 2828 return len > 1 ? jQuery.uniqueSort( ret ) : ret; 2829 }, 2830 filter: function( selector ) { 2831 return this.pushStack( winnow( this, selector || [], false ) ); 2832 }, 2833 not: function( selector ) { 2834 return this.pushStack( winnow( this, selector || [], true ) ); 2835 }, 2836 is: function( selector ) { 2837 return !!winnow( 2838 this, 2839 2840 // If this is a positional/relative selector, check membership in the returned set 2841 // so $("p:first").is("p:last") won't return true for a doc with two "p". 2842 typeof selector === "string" && rneedsContext.test( selector ) ? 2843 jQuery( selector ) : 2844 selector || [], 2845 false 2846 ).length; 2847 } 2848} ); 2849 2850 2851// Initialize a jQuery object 2852 2853 2854// A central reference to the root jQuery(document) 2855var rootjQuery, 2856 2857 // A simple way to check for HTML strings 2858 // Prioritize #id over <tag> to avoid XSS via location.hash (trac-9521) 2859 // Strict HTML recognition (trac-11290: must start with <) 2860 // Shortcut simple #id case for speed 2861 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, 2862 2863 init = jQuery.fn.init = function( selector, context, root ) { 2864 var match, elem; 2865 2866 // HANDLE: $(""), $(null), $(undefined), $(false) 2867 if ( !selector ) { 2868 return this; 2869 } 2870 2871 // Method init() accepts an alternate rootjQuery 2872 // so migrate can support jQuery.sub (gh-2101) 2873 root = root || rootjQuery; 2874 2875 // Handle HTML strings 2876 if ( typeof selector === "string" ) { 2877 if ( selector[ 0 ] === "<" && 2878 selector[ selector.length - 1 ] === ">" && 2879 selector.length >= 3 ) { 2880 2881 // Assume that strings that start and end with <> are HTML and skip the regex check 2882 match = [ null, selector, null ]; 2883 2884 } else { 2885 match = rquickExpr.exec( selector ); 2886 } 2887 2888 // Match html or make sure no context is specified for #id 2889 if ( match && ( match[ 1 ] || !context ) ) { 2890 2891 // HANDLE: $(html) -> $(array) 2892 if ( match[ 1 ] ) { 2893 context = context instanceof jQuery ? context[ 0 ] : context; 2894 2895 // Option to run scripts is true for back-compat 2896 // Intentionally let the error be thrown if parseHTML is not present 2897 jQuery.merge( this, jQuery.parseHTML( 2898 match[ 1 ], 2899 context && context.nodeType ? context.ownerDocument || context : document, 2900 true 2901 ) ); 2902 2903 // HANDLE: $(html, props) 2904 if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { 2905 for ( match in context ) { 2906 2907 // Properties of context are called as methods if possible 2908 if ( isFunction( this[ match ] ) ) { 2909 this[ match ]( context[ match ] ); 2910 2911 // ...and otherwise set as attributes 2912 } else { 2913 this.attr( match, context[ match ] ); 2914 } 2915 } 2916 } 2917 2918 return this; 2919 2920 // HANDLE: $(#id) 2921 } else { 2922 elem = document.getElementById( match[ 2 ] ); 2923 2924 if ( elem ) { 2925 2926 // Inject the element directly into the jQuery object 2927 this[ 0 ] = elem; 2928 this.length = 1; 2929 } 2930 return this; 2931 } 2932 2933 // HANDLE: $(expr, $(...)) 2934 } else if ( !context || context.jquery ) { 2935 return ( context || root ).find( selector ); 2936 2937 // HANDLE: $(expr, context) 2938 // (which is just equivalent to: $(context).find(expr) 2939 } else { 2940 return this.constructor( context ).find( selector ); 2941 } 2942 2943 // HANDLE: $(DOMElement) 2944 } else if ( selector.nodeType ) { 2945 this[ 0 ] = selector; 2946 this.length = 1; 2947 return this; 2948 2949 // HANDLE: $(function) 2950 // Shortcut for document ready 2951 } else if ( isFunction( selector ) ) { 2952 return root.ready !== undefined ? 2953 root.ready( selector ) : 2954 2955 // Execute immediately if ready is not present 2956 selector( jQuery ); 2957 } 2958 2959 return jQuery.makeArray( selector, this ); 2960 }; 2961 2962// Give the init function the jQuery prototype for later instantiation 2963init.prototype = jQuery.fn; 2964 2965// Initialize central reference 2966rootjQuery = jQuery( document ); 2967 2968 2969var rparentsprev = /^(?:parents|prev(?:Until|All))/, 2970 2971 // Methods guaranteed to produce a unique set when starting from a unique set 2972 guaranteedUnique = { 2973 children: true, 2974 contents: true, 2975 next: true, 2976 prev: true 2977 }; 2978 2979jQuery.fn.extend( { 2980 has: function( target ) { 2981 var targets = jQuery( target, this ), 2982 l = targets.length; 2983 2984 return this.filter( function() { 2985 var i = 0; 2986 for ( ; i < l; i++ ) { 2987 if ( jQuery.contains( this, targets[ i ] ) ) { 2988 return true; 2989 } 2990 } 2991 } ); 2992 }, 2993 2994 closest: function( selectors, context ) { 2995 var cur, 2996 i = 0, 2997 l = this.length, 2998 matched = [], 2999 targets = typeof selectors !== "string" && jQuery( selectors ); 3000 3001 // Positional selectors never match, since there's no _selection_ context 3002 if ( !rneedsContext.test( selectors ) ) { 3003 for ( ; i < l; i++ ) { 3004 for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { 3005 3006 // Always skip document fragments 3007 if ( cur.nodeType < 11 && ( targets ? 3008 targets.index( cur ) > -1 : 3009 3010 // Don't pass non-elements to jQuery#find 3011 cur.nodeType === 1 && 3012 jQuery.find.matchesSelector( cur, selectors ) ) ) { 3013 3014 matched.push( cur ); 3015 break; 3016 } 3017 } 3018 } 3019 } 3020 3021 return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); 3022 }, 3023 3024 // Determine the position of an element within the set 3025 index: function( elem ) { 3026 3027 // No argument, return index in parent 3028 if ( !elem ) { 3029 return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; 3030 } 3031 3032 // Index in selector 3033 if ( typeof elem === "string" ) { 3034 return indexOf.call( jQuery( elem ), this[ 0 ] ); 3035 } 3036 3037 // Locate the position of the desired element 3038 return indexOf.call( this, 3039 3040 // If it receives a jQuery object, the first element is used 3041 elem.jquery ? elem[ 0 ] : elem 3042 ); 3043 }, 3044 3045 add: function( selector, context ) { 3046 return this.pushStack( 3047 jQuery.uniqueSort( 3048 jQuery.merge( this.get(), jQuery( selector, context ) ) 3049 ) 3050 ); 3051 }, 3052 3053 addBack: function( selector ) { 3054 return this.add( selector == null ? 3055 this.prevObject : this.prevObject.filter( selector ) 3056 ); 3057 } 3058} ); 3059 3060function sibling( cur, dir ) { 3061 while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} 3062 return cur; 3063} 3064 3065jQuery.each( { 3066 parent: function( elem ) { 3067 var parent = elem.parentNode; 3068 return parent && parent.nodeType !== 11 ? parent : null; 3069 }, 3070 parents: function( elem ) { 3071 return dir( elem, "parentNode" ); 3072 }, 3073 parentsUntil: function( elem, _i, until ) { 3074 return dir( elem, "parentNode", until ); 3075 }, 3076 next: function( elem ) { 3077 return sibling( elem, "nextSibling" ); 3078 }, 3079 prev: function( elem ) { 3080 return sibling( elem, "previousSibling" ); 3081 }, 3082 nextAll: function( elem ) { 3083 return dir( elem, "nextSibling" ); 3084 }, 3085 prevAll: function( elem ) { 3086 return dir( elem, "previousSibling" ); 3087 }, 3088 nextUntil: function( elem, _i, until ) { 3089 return dir( elem, "nextSibling", until ); 3090 }, 3091 prevUntil: function( elem, _i, until ) { 3092 return dir( elem, "previousSibling", until ); 3093 }, 3094 siblings: function( elem ) { 3095 return siblings( ( elem.parentNode || {} ).firstChild, elem ); 3096 }, 3097 children: function( elem ) { 3098 return siblings( elem.firstChild ); 3099 }, 3100 contents: function( elem ) { 3101 if ( elem.contentDocument != null && 3102 3103 // Support: IE 11+ 3104 // <object> elements with no `data` attribute has an object 3105 // `contentDocument` with a `null` prototype. 3106 getProto( elem.contentDocument ) ) { 3107 3108 return elem.contentDocument; 3109 } 3110 3111 // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only 3112 // Treat the template element as a regular one in browsers that 3113 // don't support it. 3114 if ( nodeName( elem, "template" ) ) { 3115 elem = elem.content || elem; 3116 } 3117 3118 return jQuery.merge( [], elem.childNodes ); 3119 } 3120}, function( name, fn ) { 3121 jQuery.fn[ name ] = function( until, selector ) { 3122 var matched = jQuery.map( this, fn, until ); 3123 3124 if ( name.slice( -5 ) !== "Until" ) { 3125 selector = until; 3126 } 3127 3128 if ( selector && typeof selector === "string" ) { 3129 matched = jQuery.filter( selector, matched ); 3130 } 3131 3132 if ( this.length > 1 ) { 3133 3134 // Remove duplicates 3135 if ( !guaranteedUnique[ name ] ) { 3136 jQuery.uniqueSort( matched ); 3137 } 3138 3139 // Reverse order for parents* and prev-derivatives 3140 if ( rparentsprev.test( name ) ) { 3141 matched.reverse(); 3142 } 3143 } 3144 3145 return this.pushStack( matched ); 3146 }; 3147} ); 3148var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); 3149 3150 3151 3152// Convert String-formatted options into Object-formatted ones 3153function createOptions( options ) { 3154 var object = {}; 3155 jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { 3156 object[ flag ] = true; 3157 } ); 3158 return object; 3159} 3160 3161/* 3162 * Create a callback list using the following parameters: 3163 * 3164 * options: an optional list of space-separated options that will change how 3165 * the callback list behaves or a more traditional option object 3166 * 3167 * By default a callback list will act like an event callback list and can be 3168 * "fired" multiple times. 3169 * 3170 * Possible options: 3171 * 3172 * once: will ensure the callback list can only be fired once (like a Deferred) 3173 * 3174 * memory: will keep track of previous values and will call any callback added 3175 * after the list has been fired right away with the latest "memorized" 3176 * values (like a Deferred) 3177 * 3178 * unique: will ensure a callback can only be added once (no duplicate in the list) 3179 * 3180 * stopOnFalse: interrupt callings when a callback returns false 3181 * 3182 */ 3183jQuery.Callbacks = function( options ) { 3184 3185 // Convert options from String-formatted to Object-formatted if needed 3186 // (we check in cache first) 3187 options = typeof options === "string" ? 3188 createOptions( options ) : 3189 jQuery.extend( {}, options ); 3190 3191 var // Flag to know if list is currently firing 3192 firing, 3193 3194 // Last fire value for non-forgettable lists 3195 memory, 3196 3197 // Flag to know if list was already fired 3198 fired, 3199 3200 // Flag to prevent firing 3201 locked, 3202 3203 // Actual callback list 3204 list = [], 3205 3206 // Queue of execution data for repeatable lists 3207 queue = [], 3208 3209 // Index of currently firing callback (modified by add/remove as needed) 3210 firingIndex = -1, 3211 3212 // Fire callbacks 3213 fire = function() { 3214 3215 // Enforce single-firing 3216 locked = locked || options.once; 3217 3218 // Execute callbacks for all pending executions, 3219 // respecting firingIndex overrides and runtime changes 3220 fired = firing = true; 3221 for ( ; queue.length; firingIndex = -1 ) { 3222 memory = queue.shift(); 3223 while ( ++firingIndex < list.length ) { 3224 3225 // Run callback and check for early termination 3226 if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && 3227 options.stopOnFalse ) { 3228 3229 // Jump to end and forget the data so .add doesn't re-fire 3230 firingIndex = list.length; 3231 memory = false; 3232 } 3233 } 3234 } 3235 3236 // Forget the data if we're done with it 3237 if ( !options.memory ) { 3238 memory = false; 3239 } 3240 3241 firing = false; 3242 3243 // Clean up if we're done firing for good 3244 if ( locked ) { 3245 3246 // Keep an empty list if we have data for future add calls 3247 if ( memory ) { 3248 list = []; 3249 3250 // Otherwise, this object is spent 3251 } else { 3252 list = ""; 3253 } 3254 } 3255 }, 3256 3257 // Actual Callbacks object 3258 self = { 3259 3260 // Add a callback or a collection of callbacks to the list 3261 add: function() { 3262 if ( list ) { 3263 3264 // If we have memory from a past run, we should fire after adding 3265 if ( memory && !firing ) { 3266 firingIndex = list.length - 1; 3267 queue.push( memory ); 3268 } 3269 3270 ( function add( args ) { 3271 jQuery.each( args, function( _, arg ) { 3272 if ( isFunction( arg ) ) { 3273 if ( !options.unique || !self.has( arg ) ) { 3274 list.push( arg ); 3275 } 3276 } else if ( arg && arg.length && toType( arg ) !== "string" ) { 3277 3278 // Inspect recursively 3279 add( arg ); 3280 } 3281 } ); 3282 } )( arguments ); 3283 3284 if ( memory && !firing ) { 3285 fire(); 3286 } 3287 } 3288 return this; 3289 }, 3290 3291 // Remove a callback from the list 3292 remove: function() { 3293 jQuery.each( arguments, function( _, arg ) { 3294 var index; 3295 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { 3296 list.splice( index, 1 ); 3297 3298 // Handle firing indexes 3299 if ( index <= firingIndex ) { 3300 firingIndex--; 3301 } 3302 } 3303 } ); 3304 return this; 3305 }, 3306 3307 // Check if a given callback is in the list. 3308 // If no argument is given, return whether or not list has callbacks attached. 3309 has: function( fn ) { 3310 return fn ? 3311 jQuery.inArray( fn, list ) > -1 : 3312 list.length > 0; 3313 }, 3314 3315 // Remove all callbacks from the list 3316 empty: function() { 3317 if ( list ) { 3318 list = []; 3319 } 3320 return this; 3321 }, 3322 3323 // Disable .fire and .add 3324 // Abort any current/pending executions 3325 // Clear all callbacks and values 3326 disable: function() { 3327 locked = queue = []; 3328 list = memory = ""; 3329 return this; 3330 }, 3331 disabled: function() { 3332 return !list; 3333 }, 3334 3335 // Disable .fire 3336 // Also disable .add unless we have memory (since it would have no effect) 3337 // Abort any pending executions 3338 lock: function() { 3339 locked = queue = []; 3340 if ( !memory && !firing ) { 3341 list = memory = ""; 3342 } 3343 return this; 3344 }, 3345 locked: function() { 3346 return !!locked; 3347 }, 3348 3349 // Call all callbacks with the given context and arguments 3350 fireWith: function( context, args ) { 3351 if ( !locked ) { 3352 args = args || []; 3353 args = [ context, args.slice ? args.slice() : args ]; 3354 queue.push( args ); 3355 if ( !firing ) { 3356 fire(); 3357 } 3358 } 3359 return this; 3360 }, 3361 3362 // Call all the callbacks with the given arguments 3363 fire: function() { 3364 self.fireWith( this, arguments ); 3365 return this; 3366 }, 3367 3368 // To know if the callbacks have already been called at least once 3369 fired: function() { 3370 return !!fired; 3371 } 3372 }; 3373 3374 return self; 3375}; 3376 3377 3378function Identity( v ) { 3379 return v; 3380} 3381function Thrower( ex ) { 3382 throw ex; 3383} 3384 3385function adoptValue( value, resolve, reject, noValue ) { 3386 var method; 3387 3388 try { 3389 3390 // Check for promise aspect first to privilege synchronous behavior 3391 if ( value && isFunction( ( method = value.promise ) ) ) { 3392 method.call( value ).done( resolve ).fail( reject ); 3393 3394 // Other thenables 3395 } else if ( value && isFunction( ( method = value.then ) ) ) { 3396 method.call( value, resolve, reject ); 3397 3398 // Other non-thenables 3399 } else { 3400 3401 // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: 3402 // * false: [ value ].slice( 0 ) => resolve( value ) 3403 // * true: [ value ].slice( 1 ) => resolve() 3404 resolve.apply( undefined, [ value ].slice( noValue ) ); 3405 } 3406 3407 // For Promises/A+, convert exceptions into rejections 3408 // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in 3409 // Deferred#then to conditionally suppress rejection. 3410 } catch ( value ) { 3411 3412 // Support: Android 4.0 only 3413 // Strict mode functions invoked without .call/.apply get global-object context 3414 reject.apply( undefined, [ value ] ); 3415 } 3416} 3417 3418jQuery.extend( { 3419 3420 Deferred: function( func ) { 3421 var tuples = [ 3422 3423 // action, add listener, callbacks, 3424 // ... .then handlers, argument index, [final state] 3425 [ "notify", "progress", jQuery.Callbacks( "memory" ), 3426 jQuery.Callbacks( "memory" ), 2 ], 3427 [ "resolve", "done", jQuery.Callbacks( "once memory" ), 3428 jQuery.Callbacks( "once memory" ), 0, "resolved" ], 3429 [ "reject", "fail", jQuery.Callbacks( "once memory" ), 3430 jQuery.Callbacks( "once memory" ), 1, "rejected" ] 3431 ], 3432 state = "pending", 3433 promise = { 3434 state: function() { 3435 return state; 3436 }, 3437 always: function() { 3438 deferred.done( arguments ).fail( arguments ); 3439 return this; 3440 }, 3441 "catch": function( fn ) { 3442 return promise.then( null, fn ); 3443 }, 3444 3445 // Keep pipe for back-compat 3446 pipe: function( /* fnDone, fnFail, fnProgress */ ) { 3447 var fns = arguments; 3448 3449 return jQuery.Deferred( function( newDefer ) { 3450 jQuery.each( tuples, function( _i, tuple ) { 3451 3452 // Map tuples (progress, done, fail) to arguments (done, fail, progress) 3453 var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; 3454 3455 // deferred.progress(function() { bind to newDefer or newDefer.notify }) 3456 // deferred.done(function() { bind to newDefer or newDefer.resolve }) 3457 // deferred.fail(function() { bind to newDefer or newDefer.reject }) 3458 deferred[ tuple[ 1 ] ]( function() { 3459 var returned = fn && fn.apply( this, arguments ); 3460 if ( returned && isFunction( returned.promise ) ) { 3461 returned.promise() 3462 .progress( newDefer.notify ) 3463 .done( newDefer.resolve ) 3464 .fail( newDefer.reject ); 3465 } else { 3466 newDefer[ tuple[ 0 ] + "With" ]( 3467 this, 3468 fn ? [ returned ] : arguments 3469 ); 3470 } 3471 } ); 3472 } ); 3473 fns = null; 3474 } ).promise(); 3475 }, 3476 then: function( onFulfilled, onRejected, onProgress ) { 3477 var maxDepth = 0; 3478 function resolve( depth, deferred, handler, special ) { 3479 return function() { 3480 var that = this, 3481 args = arguments, 3482 mightThrow = function() { 3483 var returned, then; 3484 3485 // Support: Promises/A+ section 2.3.3.3.3 3486 // https://promisesaplus.com/#point-59 3487 // Ignore double-resolution attempts 3488 if ( depth < maxDepth ) { 3489 return; 3490 } 3491 3492 returned = handler.apply( that, args ); 3493 3494 // Support: Promises/A+ section 2.3.1 3495 // https://promisesaplus.com/#point-48 3496 if ( returned === deferred.promise() ) { 3497 throw new TypeError( "Thenable self-resolution" ); 3498 } 3499 3500 // Support: Promises/A+ sections 2.3.3.1, 3.5 3501 // https://promisesaplus.com/#point-54 3502 // https://promisesaplus.com/#point-75 3503 // Retrieve `then` only once 3504 then = returned && 3505 3506 // Support: Promises/A+ section 2.3.4 3507 // https://promisesaplus.com/#point-64 3508 // Only check objects and functions for thenability 3509 ( typeof returned === "object" || 3510 typeof returned === "function" ) && 3511 returned.then; 3512 3513 // Handle a returned thenable 3514 if ( isFunction( then ) ) { 3515 3516 // Special processors (notify) just wait for resolution 3517 if ( special ) { 3518 then.call( 3519 returned, 3520 resolve( maxDepth, deferred, Identity, special ), 3521 resolve( maxDepth, deferred, Thrower, special ) 3522 ); 3523 3524 // Normal processors (resolve) also hook into progress 3525 } else { 3526 3527 // ...and disregard older resolution values 3528 maxDepth++; 3529 3530 then.call( 3531 returned, 3532 resolve( maxDepth, deferred, Identity, special ), 3533 resolve( maxDepth, deferred, Thrower, special ), 3534 resolve( maxDepth, deferred, Identity, 3535 deferred.notifyWith ) 3536 ); 3537 } 3538 3539 // Handle all other returned values 3540 } else { 3541 3542 // Only substitute handlers pass on context 3543 // and multiple values (non-spec behavior) 3544 if ( handler !== Identity ) { 3545 that = undefined; 3546 args = [ returned ]; 3547 } 3548 3549 // Process the value(s) 3550 // Default process is resolve 3551 ( special || deferred.resolveWith )( that, args ); 3552 } 3553 }, 3554 3555 // Only normal processors (resolve) catch and reject exceptions 3556 process = special ? 3557 mightThrow : 3558 function() { 3559 try { 3560 mightThrow(); 3561 } catch ( e ) { 3562 3563 if ( jQuery.Deferred.exceptionHook ) { 3564 jQuery.Deferred.exceptionHook( e, 3565 process.error ); 3566 } 3567 3568 // Support: Promises/A+ section 2.3.3.3.4.1 3569 // https://promisesaplus.com/#point-61 3570 // Ignore post-resolution exceptions 3571 if ( depth + 1 >= maxDepth ) { 3572 3573 // Only substitute handlers pass on context 3574 // and multiple values (non-spec behavior) 3575 if ( handler !== Thrower ) { 3576 that = undefined; 3577 args = [ e ]; 3578 } 3579 3580 deferred.rejectWith( that, args ); 3581 } 3582 } 3583 }; 3584 3585 // Support: Promises/A+ section 2.3.3.3.1 3586 // https://promisesaplus.com/#point-57 3587 // Re-resolve promises immediately to dodge false rejection from 3588 // subsequent errors 3589 if ( depth ) { 3590 process(); 3591 } else { 3592 3593 // Call an optional hook to record the error, in case of exception 3594 // since it's otherwise lost when execution goes async 3595 if ( jQuery.Deferred.getErrorHook ) { 3596 process.error = jQuery.Deferred.getErrorHook(); 3597 3598 // The deprecated alias of the above. While the name suggests 3599 // returning the stack, not an error instance, jQuery just passes 3600 // it directly to `console.warn` so both will work; an instance 3601 // just better cooperates with source maps. 3602 } else if ( jQuery.Deferred.getStackHook ) { 3603 process.error = jQuery.Deferred.getStackHook(); 3604 } 3605 window.setTimeout( process ); 3606 } 3607 }; 3608 } 3609 3610 return jQuery.Deferred( function( newDefer ) { 3611 3612 // progress_handlers.add( ... ) 3613 tuples[ 0 ][ 3 ].add( 3614 resolve( 3615 0, 3616 newDefer, 3617 isFunction( onProgress ) ? 3618 onProgress : 3619 Identity, 3620 newDefer.notifyWith 3621 ) 3622 ); 3623 3624 // fulfilled_handlers.add( ... ) 3625 tuples[ 1 ][ 3 ].add( 3626 resolve( 3627 0, 3628 newDefer, 3629 isFunction( onFulfilled ) ? 3630 onFulfilled : 3631 Identity 3632 ) 3633 ); 3634 3635 // rejected_handlers.add( ... ) 3636 tuples[ 2 ][ 3 ].add( 3637 resolve( 3638 0, 3639 newDefer, 3640 isFunction( onRejected ) ? 3641 onRejected : 3642 Thrower 3643 ) 3644 ); 3645 } ).promise(); 3646 }, 3647 3648 // Get a promise for this deferred 3649 // If obj is provided, the promise aspect is added to the object 3650 promise: function( obj ) { 3651 return obj != null ? jQuery.extend( obj, promise ) : promise; 3652 } 3653 }, 3654 deferred = {}; 3655 3656 // Add list-specific methods 3657 jQuery.each( tuples, function( i, tuple ) { 3658 var list = tuple[ 2 ], 3659 stateString = tuple[ 5 ]; 3660 3661 // promise.progress = list.add 3662 // promise.done = list.add 3663 // promise.fail = list.add 3664 promise[ tuple[ 1 ] ] = list.add; 3665 3666 // Handle state 3667 if ( stateString ) { 3668 list.add( 3669 function() { 3670 3671 // state = "resolved" (i.e., fulfilled) 3672 // state = "rejected" 3673 state = stateString; 3674 }, 3675 3676 // rejected_callbacks.disable 3677 // fulfilled_callbacks.disable 3678 tuples[ 3 - i ][ 2 ].disable, 3679 3680 // rejected_handlers.disable 3681 // fulfilled_handlers.disable 3682 tuples[ 3 - i ][ 3 ].disable, 3683 3684 // progress_callbacks.lock 3685 tuples[ 0 ][ 2 ].lock, 3686 3687 // progress_handlers.lock 3688 tuples[ 0 ][ 3 ].lock 3689 ); 3690 } 3691 3692 // progress_handlers.fire 3693 // fulfilled_handlers.fire 3694 // rejected_handlers.fire 3695 list.add( tuple[ 3 ].fire ); 3696 3697 // deferred.notify = function() { deferred.notifyWith(...) } 3698 // deferred.resolve = function() { deferred.resolveWith(...) } 3699 // deferred.reject = function() { deferred.rejectWith(...) } 3700 deferred[ tuple[ 0 ] ] = function() { 3701 deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); 3702 return this; 3703 }; 3704 3705 // deferred.notifyWith = list.fireWith 3706 // deferred.resolveWith = list.fireWith 3707 // deferred.rejectWith = list.fireWith 3708 deferred[ tuple[ 0 ] + "With" ] = list.fireWith; 3709 } ); 3710 3711 // Make the deferred a promise 3712 promise.promise( deferred ); 3713 3714 // Call given func if any 3715 if ( func ) { 3716 func.call( deferred, deferred ); 3717 } 3718 3719 // All done! 3720 return deferred; 3721 }, 3722 3723 // Deferred helper 3724 when: function( singleValue ) { 3725 var 3726 3727 // count of uncompleted subordinates 3728 remaining = arguments.length, 3729 3730 // count of unprocessed arguments 3731 i = remaining, 3732 3733 // subordinate fulfillment data 3734 resolveContexts = Array( i ), 3735 resolveValues = slice.call( arguments ), 3736 3737 // the primary Deferred 3738 primary = jQuery.Deferred(), 3739 3740 // subordinate callback factory 3741 updateFunc = function( i ) { 3742 return function( value ) { 3743 resolveContexts[ i ] = this; 3744 resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; 3745 if ( !( --remaining ) ) { 3746 primary.resolveWith( resolveContexts, resolveValues ); 3747 } 3748 }; 3749 }; 3750 3751 // Single- and empty arguments are adopted like Promise.resolve 3752 if ( remaining <= 1 ) { 3753 adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, 3754 !remaining ); 3755 3756 // Use .then() to unwrap secondary thenables (cf. gh-3000) 3757 if ( primary.state() === "pending" || 3758 isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { 3759 3760 return primary.then(); 3761 } 3762 } 3763 3764 // Multiple arguments are aggregated like Promise.all array elements 3765 while ( i-- ) { 3766 adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); 3767 } 3768 3769 return primary.promise(); 3770 } 3771} ); 3772 3773 3774// These usually indicate a programmer mistake during development, 3775// warn about them ASAP rather than swallowing them by default. 3776var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; 3777 3778// If `jQuery.Deferred.getErrorHook` is defined, `asyncError` is an error 3779// captured before the async barrier to get the original error cause 3780// which may otherwise be hidden. 3781jQuery.Deferred.exceptionHook = function( error, asyncError ) { 3782 3783 // Support: IE 8 - 9 only 3784 // Console exists when dev tools are open, which can happen at any time 3785 if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { 3786 window.console.warn( "jQuery.Deferred exception: " + error.message, 3787 error.stack, asyncError ); 3788 } 3789}; 3790 3791 3792 3793 3794jQuery.readyException = function( error ) { 3795 window.setTimeout( function() { 3796 throw error; 3797 } ); 3798}; 3799 3800 3801 3802 3803// The deferred used on DOM ready 3804var readyList = jQuery.Deferred(); 3805 3806jQuery.fn.ready = function( fn ) { 3807 3808 readyList 3809 .then( fn ) 3810 3811 // Wrap jQuery.readyException in a function so that the lookup 3812 // happens at the time of error handling instead of callback 3813 // registration. 3814 .catch( function( error ) { 3815 jQuery.readyException( error ); 3816 } ); 3817 3818 return this; 3819}; 3820 3821jQuery.extend( { 3822 3823 // Is the DOM ready to be used? Set to true once it occurs. 3824 isReady: false, 3825 3826 // A counter to track how many items to wait for before 3827 // the ready event fires. See trac-6781 3828 readyWait: 1, 3829 3830 // Handle when the DOM is ready 3831 ready: function( wait ) { 3832 3833 // Abort if there are pending holds or we're already ready 3834 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { 3835 return; 3836 } 3837 3838 // Remember that the DOM is ready 3839 jQuery.isReady = true; 3840 3841 // If a normal DOM Ready event fired, decrement, and wait if need be 3842 if ( wait !== true && --jQuery.readyWait > 0 ) { 3843 return; 3844 } 3845 3846 // If there are functions bound, to execute 3847 readyList.resolveWith( document, [ jQuery ] ); 3848 } 3849} ); 3850 3851jQuery.ready.then = readyList.then; 3852 3853// The ready event handler and self cleanup method 3854function completed() { 3855 document.removeEventListener( "DOMContentLoaded", completed ); 3856 window.removeEventListener( "load", completed ); 3857 jQuery.ready(); 3858} 3859 3860// Catch cases where $(document).ready() is called 3861// after the browser event has already occurred. 3862// Support: IE <=9 - 10 only 3863// Older IE sometimes signals "interactive" too soon 3864if ( document.readyState === "complete" || 3865 ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { 3866 3867 // Handle it asynchronously to allow scripts the opportunity to delay ready 3868 window.setTimeout( jQuery.ready ); 3869 3870} else { 3871 3872 // Use the handy event callback 3873 document.addEventListener( "DOMContentLoaded", completed ); 3874 3875 // A fallback to window.onload, that will always work 3876 window.addEventListener( "load", completed ); 3877} 3878 3879 3880 3881 3882// Multifunctional method to get and set values of a collection 3883// The value/s can optionally be executed if it's a function 3884var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { 3885 var i = 0, 3886 len = elems.length, 3887 bulk = key == null; 3888 3889 // Sets many values 3890 if ( toType( key ) === "object" ) { 3891 chainable = true; 3892 for ( i in key ) { 3893 access( elems, fn, i, key[ i ], true, emptyGet, raw ); 3894 } 3895 3896 // Sets one value 3897 } else if ( value !== undefined ) { 3898 chainable = true; 3899 3900 if ( !isFunction( value ) ) { 3901 raw = true; 3902 } 3903 3904 if ( bulk ) { 3905 3906 // Bulk operations run against the entire set 3907 if ( raw ) { 3908 fn.call( elems, value ); 3909 fn = null; 3910 3911 // ...except when executing function values 3912 } else { 3913 bulk = fn; 3914 fn = function( elem, _key, value ) { 3915 return bulk.call( jQuery( elem ), value ); 3916 }; 3917 } 3918 } 3919 3920 if ( fn ) { 3921 for ( ; i < len; i++ ) { 3922 fn( 3923 elems[ i ], key, raw ? 3924 value : 3925 value.call( elems[ i ], i, fn( elems[ i ], key ) ) 3926 ); 3927 } 3928 } 3929 } 3930 3931 if ( chainable ) { 3932 return elems; 3933 } 3934 3935 // Gets 3936 if ( bulk ) { 3937 return fn.call( elems ); 3938 } 3939 3940 return len ? fn( elems[ 0 ], key ) : emptyGet; 3941}; 3942 3943 3944// Matches dashed string for camelizing 3945var rmsPrefix = /^-ms-/, 3946 rdashAlpha = /-([a-z])/g; 3947 3948// Used by camelCase as callback to replace() 3949function fcamelCase( _all, letter ) { 3950 return letter.toUpperCase(); 3951} 3952 3953// Convert dashed to camelCase; used by the css and data modules 3954// Support: IE <=9 - 11, Edge 12 - 15 3955// Microsoft forgot to hump their vendor prefix (trac-9572) 3956function camelCase( string ) { 3957 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); 3958} 3959var acceptData = function( owner ) { 3960 3961 // Accepts only: 3962 // - Node 3963 // - Node.ELEMENT_NODE 3964 // - Node.DOCUMENT_NODE 3965 // - Object 3966 // - Any 3967 return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); 3968}; 3969 3970 3971 3972 3973function Data() { 3974 this.expando = jQuery.expando + Data.uid++; 3975} 3976 3977Data.uid = 1; 3978 3979Data.prototype = { 3980 3981 cache: function( owner ) { 3982 3983 // Check if the owner object already has a cache 3984 var value = owner[ this.expando ]; 3985 3986 // If not, create one 3987 if ( !value ) { 3988 value = {}; 3989 3990 // We can accept data for non-element nodes in modern browsers, 3991 // but we should not, see trac-8335. 3992 // Always return an empty object. 3993 if ( acceptData( owner ) ) { 3994 3995 // If it is a node unlikely to be stringify-ed or looped over 3996 // use plain assignment 3997 if ( owner.nodeType ) { 3998 owner[ this.expando ] = value; 3999 4000 // Otherwise secure it in a non-enumerable property 4001 // configurable must be true to allow the property to be 4002 // deleted when data is removed 4003 } else { 4004 Object.defineProperty( owner, this.expando, { 4005 value: value, 4006 configurable: true 4007 } ); 4008 } 4009 } 4010 } 4011 4012 return value; 4013 }, 4014 set: function( owner, data, value ) { 4015 var prop, 4016 cache = this.cache( owner ); 4017 4018 // Handle: [ owner, key, value ] args 4019 // Always use camelCase key (gh-2257) 4020 if ( typeof data === "string" ) { 4021 cache[ camelCase( data ) ] = value; 4022 4023 // Handle: [ owner, { properties } ] args 4024 } else { 4025 4026 // Copy the properties one-by-one to the cache object 4027 for ( prop in data ) { 4028 cache[ camelCase( prop ) ] = data[ prop ]; 4029 } 4030 } 4031 return cache; 4032 }, 4033 get: function( owner, key ) { 4034 return key === undefined ? 4035 this.cache( owner ) : 4036 4037 // Always use camelCase key (gh-2257) 4038 owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; 4039 }, 4040 access: function( owner, key, value ) { 4041 4042 // In cases where either: 4043 // 4044 // 1. No key was specified 4045 // 2. A string key was specified, but no value provided 4046 // 4047 // Take the "read" path and allow the get method to determine 4048 // which value to return, respectively either: 4049 // 4050 // 1. The entire cache object 4051 // 2. The data stored at the key 4052 // 4053 if ( key === undefined || 4054 ( ( key && typeof key === "string" ) && value === undefined ) ) { 4055 4056 return this.get( owner, key ); 4057 } 4058 4059 // When the key is not a string, or both a key and value 4060 // are specified, set or extend (existing objects) with either: 4061 // 4062 // 1. An object of properties 4063 // 2. A key and value 4064 // 4065 this.set( owner, key, value ); 4066 4067 // Since the "set" path can have two possible entry points 4068 // return the expected data based on which path was taken[*] 4069 return value !== undefined ? value : key; 4070 }, 4071 remove: function( owner, key ) { 4072 var i, 4073 cache = owner[ this.expando ]; 4074 4075 if ( cache === undefined ) { 4076 return; 4077 } 4078 4079 if ( key !== undefined ) { 4080
vendor: 4,799 bytes, lines 4081-4263
4081 // Support array or space separated string of keys 4082 if ( Array.isArray( key ) ) { 4083 4084 // If key is an array of keys... 4085 // We always set camelCase keys, so remove that. 4086 key = key.map( camelCase ); 4087 } else { 4088 key = camelCase( key ); 4089 4090 // If a key with the spaces exists, use it. 4091 // Otherwise, create an array by matching non-whitespace 4092 key = key in cache ? 4093 [ key ] : 4094 ( key.match( rnothtmlwhite ) || [] ); 4095 } 4096 4097 i = key.length; 4098 4099 while ( i-- ) { 4100 delete cache[ key[ i ] ]; 4101 } 4102 } 4103 4104 // Remove the expando if there's no more data 4105 if ( key === undefined || jQuery.isEmptyObject( cache ) ) { 4106 4107 // Support: Chrome <=35 - 45 4108 // Webkit & Blink performance suffers when deleting properties 4109 // from DOM nodes, so set to undefined instead 4110 // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) 4111 if ( owner.nodeType ) { 4112 owner[ this.expando ] = undefined; 4113 } else { 4114 delete owner[ this.expando ]; 4115 } 4116 } 4117 }, 4118 hasData: function( owner ) { 4119 var cache = owner[ this.expando ]; 4120 return cache !== undefined && !jQuery.isEmptyObject( cache ); 4121 } 4122}; 4123var dataPriv = new Data(); 4124 4125var dataUser = new Data(); 4126 4127 4128 4129// Implementation Summary 4130// 4131// 1. Enforce API surface and semantic compatibility with 1.9.x branch 4132// 2. Improve the module's maintainability by reducing the storage 4133// paths to a single mechanism. 4134// 3. Use the same single mechanism to support "private" and "user" data. 4135// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) 4136// 5. Avoid exposing implementation details on user objects (eg. expando properties) 4137// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 4138 4139var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, 4140 rmultiDash = /[A-Z]/g; 4141 4142function getData( data ) { 4143 if ( data === "true" ) { 4144 return true; 4145 } 4146 4147 if ( data === "false" ) { 4148 return false; 4149 } 4150 4151 if ( data === "null" ) { 4152 return null; 4153 } 4154 4155 // Only convert to a number if it doesn't change the string 4156 if ( data === +data + "" ) { 4157 return +data; 4158 } 4159 4160 if ( rbrace.test( data ) ) { 4161 return JSON.parse( data ); 4162 } 4163 4164 return data; 4165} 4166 4167function dataAttr( elem, key, data ) { 4168 var name; 4169 4170 // If nothing was found internally, try to fetch any 4171 // data from the HTML5 data-* attribute 4172 if ( data === undefined && elem.nodeType === 1 ) { 4173 name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); 4174 data = elem.getAttribute( name ); 4175 4176 if ( typeof data === "string" ) { 4177 try { 4178 data = getData( data ); 4179 } catch ( e ) {} 4180 4181 // Make sure we set the data so it isn't changed later 4182 dataUser.set( elem, key, data ); 4183 } else { 4184 data = undefined; 4185 } 4186 } 4187 return data; 4188} 4189 4190jQuery.extend( { 4191 hasData: function( elem ) { 4192 return dataUser.hasData( elem ) || dataPriv.hasData( elem ); 4193 }, 4194 4195 data: function( elem, name, data ) { 4196 return dataUser.access( elem, name, data ); 4197 }, 4198 4199 removeData: function( elem, name ) { 4200 dataUser.remove( elem, name ); 4201 }, 4202 4203 // TODO: Now that all calls to _data and _removeData have been replaced 4204 // with direct calls to dataPriv methods, these can be deprecated. 4205 _data: function( elem, name, data ) { 4206 return dataPriv.access( elem, name, data ); 4207 }, 4208 4209 _removeData: function( elem, name ) { 4210 dataPriv.remove( elem, name ); 4211 } 4212} ); 4213 4214jQuery.fn.extend( { 4215 data: function( key, value ) { 4216 var i, name, data, 4217 elem = this[ 0 ], 4218 attrs = elem && elem.attributes; 4219 4220 // Gets all values 4221 if ( key === undefined ) { 4222 if ( this.length ) { 4223 data = dataUser.get( elem ); 4224 4225 if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { 4226 i = attrs.length; 4227 while ( i-- ) { 4228 4229 // Support: IE 11 only 4230 // The attrs elements can be null (trac-14894) 4231 if ( attrs[ i ] ) { 4232 name = attrs[ i ].name; 4233 if ( name.indexOf( "data-" ) === 0 ) { 4234 name = camelCase( name.slice( 5 ) ); 4235 dataAttr( elem, name, data[ name ] ); 4236 } 4237 } 4238 } 4239 dataPriv.set( elem, "hasDataAttrs", true ); 4240 } 4241 } 4242 4243 return data; 4244 } 4245 4246 // Sets multiple values 4247 if ( typeof key === "object" ) { 4248 return this.each( function() { 4249 dataUser.set( this, key ); 4250 } ); 4251 } 4252 4253 return access( this, function( value ) { 4254 var data; 4255 4256 // The calling jQuery object (element matches) is not empty 4257 // (and therefore has an element appears at this[ 0 ]) and the 4258 // `value` parameter was not undefined. An empty jQuery object 4259 // will result in `undefined` for elem = this[ 0 ] which will 4260 // throw an exception if an attempt to read a data cache is made. 4261 if ( elem && value === undefined ) { 4262 4263 // Attempt to get data from the cache
vendor: 20,334 bytes, lines 4264-5037
4264 // The key will always be camelCased in Data 4265 data = dataUser.get( elem, key ); 4266 if ( data !== undefined ) { 4267 return data; 4268 } 4269 4270 // Attempt to "discover" the data in 4271 // HTML5 custom data-* attrs 4272 data = dataAttr( elem, key ); 4273 if ( data !== undefined ) { 4274 return data; 4275 } 4276 4277 // We tried really hard, but the data doesn't exist. 4278 return; 4279 } 4280 4281 // Set the data... 4282 this.each( function() { 4283 4284 // We always store the camelCased key 4285 dataUser.set( this, key, value ); 4286 } ); 4287 }, null, value, arguments.length > 1, null, true ); 4288 }, 4289 4290 removeData: function( key ) { 4291 return this.each( function() { 4292 dataUser.remove( this, key ); 4293 } ); 4294 } 4295} ); 4296 4297 4298jQuery.extend( { 4299 queue: function( elem, type, data ) { 4300 var queue; 4301 4302 if ( elem ) { 4303 type = ( type || "fx" ) + "queue"; 4304 queue = dataPriv.get( elem, type ); 4305 4306 // Speed up dequeue by getting out quickly if this is just a lookup 4307 if ( data ) { 4308 if ( !queue || Array.isArray( data ) ) { 4309 queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); 4310 } else { 4311 queue.push( data ); 4312 } 4313 } 4314 return queue || []; 4315 } 4316 }, 4317 4318 dequeue: function( elem, type ) { 4319 type = type || "fx"; 4320 4321 var queue = jQuery.queue( elem, type ), 4322 startLength = queue.length, 4323 fn = queue.shift(), 4324 hooks = jQuery._queueHooks( elem, type ), 4325 next = function() { 4326 jQuery.dequeue( elem, type ); 4327 }; 4328 4329 // If the fx queue is dequeued, always remove the progress sentinel 4330 if ( fn === "inprogress" ) { 4331 fn = queue.shift(); 4332 startLength--; 4333 } 4334 4335 if ( fn ) { 4336 4337 // Add a progress sentinel to prevent the fx queue from being 4338 // automatically dequeued 4339 if ( type === "fx" ) { 4340 queue.unshift( "inprogress" ); 4341 } 4342 4343 // Clear up the last queue stop function 4344 delete hooks.stop; 4345 fn.call( elem, next, hooks ); 4346 } 4347 4348 if ( !startLength && hooks ) { 4349 hooks.empty.fire(); 4350 } 4351 }, 4352 4353 // Not public - generate a queueHooks object, or return the current one 4354 _queueHooks: function( elem, type ) { 4355 var key = type + "queueHooks"; 4356 return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { 4357 empty: jQuery.Callbacks( "once memory" ).add( function() { 4358 dataPriv.remove( elem, [ type + "queue", key ] ); 4359 } ) 4360 } ); 4361 } 4362} ); 4363 4364jQuery.fn.extend( { 4365 queue: function( type, data ) { 4366 var setter = 2; 4367 4368 if ( typeof type !== "string" ) { 4369 data = type; 4370 type = "fx"; 4371 setter--; 4372 } 4373 4374 if ( arguments.length < setter ) { 4375 return jQuery.queue( this[ 0 ], type ); 4376 } 4377 4378 return data === undefined ? 4379 this : 4380 this.each( function() { 4381 var queue = jQuery.queue( this, type, data ); 4382 4383 // Ensure a hooks for this queue 4384 jQuery._queueHooks( this, type ); 4385 4386 if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { 4387 jQuery.dequeue( this, type ); 4388 } 4389 } ); 4390 }, 4391 dequeue: function( type ) { 4392 return this.each( function() { 4393 jQuery.dequeue( this, type ); 4394 } ); 4395 }, 4396 clearQueue: function( type ) { 4397 return this.queue( type || "fx", [] ); 4398 }, 4399 4400 // Get a promise resolved when queues of a certain type 4401 // are emptied (fx is the type by default) 4402 promise: function( type, obj ) { 4403 var tmp, 4404 count = 1, 4405 defer = jQuery.Deferred(), 4406 elements = this, 4407 i = this.length, 4408 resolve = function() { 4409 if ( !( --count ) ) { 4410 defer.resolveWith( elements, [ elements ] ); 4411 } 4412 }; 4413 4414 if ( typeof type !== "string" ) { 4415 obj = type; 4416 type = undefined; 4417 } 4418 type = type || "fx"; 4419 4420 while ( i-- ) { 4421 tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); 4422 if ( tmp && tmp.empty ) { 4423 count++; 4424 tmp.empty.add( resolve ); 4425 } 4426 } 4427 resolve(); 4428 return defer.promise( obj ); 4429 } 4430} ); 4431var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; 4432 4433var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); 4434 4435 4436var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; 4437 4438var documentElement = document.documentElement; 4439 4440 4441 4442 var isAttached = function( elem ) { 4443 return jQuery.contains( elem.ownerDocument, elem ); 4444 }, 4445 composed = { composed: true }; 4446 4447 // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only 4448 // Check attachment across shadow DOM boundaries when possible (gh-3504) 4449 // Support: iOS 10.0-10.2 only 4450 // Early iOS 10 versions support `attachShadow` but not `getRootNode`, 4451 // leading to errors. We need to check for `getRootNode`. 4452 if ( documentElement.getRootNode ) { 4453 isAttached = function( elem ) { 4454 return jQuery.contains( elem.ownerDocument, elem ) || 4455 elem.getRootNode( composed ) === elem.ownerDocument; 4456 }; 4457 } 4458var isHiddenWithinTree = function( elem, el ) { 4459 4460 // isHiddenWithinTree might be called from jQuery#filter function; 4461 // in that case, element will be second argument 4462 elem = el || elem; 4463 4464 // Inline style trumps all 4465 return elem.style.display === "none" || 4466 elem.style.display === "" && 4467 4468 // Otherwise, check computed style 4469 // Support: Firefox <=43 - 45 4470 // Disconnected elements can have computed display: none, so first confirm that elem is 4471 // in the document. 4472 isAttached( elem ) && 4473 4474 jQuery.css( elem, "display" ) === "none"; 4475 }; 4476 4477 4478 4479function adjustCSS( elem, prop, valueParts, tween ) { 4480 var adjusted, scale, 4481 maxIterations = 20, 4482 currentValue = tween ? 4483 function() { 4484 return tween.cur(); 4485 } : 4486 function() { 4487 return jQuery.css( elem, prop, "" ); 4488 }, 4489 initial = currentValue(), 4490 unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), 4491 4492 // Starting value computation is required for potential unit mismatches 4493 initialInUnit = elem.nodeType && 4494 ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && 4495 rcssNum.exec( jQuery.css( elem, prop ) ); 4496 4497 if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { 4498 4499 // Support: Firefox <=54 4500 // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) 4501 initial = initial / 2; 4502 4503 // Trust units reported by jQuery.css 4504 unit = unit || initialInUnit[ 3 ]; 4505 4506 // Iteratively approximate from a nonzero starting point 4507 initialInUnit = +initial || 1; 4508 4509 while ( maxIterations-- ) { 4510 4511 // Evaluate and update our best guess (doubling guesses that zero out). 4512 // Finish if the scale equals or crosses 1 (making the old*new product non-positive). 4513 jQuery.style( elem, prop, initialInUnit + unit ); 4514 if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { 4515 maxIterations = 0; 4516 } 4517 initialInUnit = initialInUnit / scale; 4518 4519 } 4520 4521 initialInUnit = initialInUnit * 2; 4522 jQuery.style( elem, prop, initialInUnit + unit ); 4523 4524 // Make sure we update the tween properties later on 4525 valueParts = valueParts || []; 4526 } 4527 4528 if ( valueParts ) { 4529 initialInUnit = +initialInUnit || +initial || 0; 4530 4531 // Apply relative offset (+=/-=) if specified 4532 adjusted = valueParts[ 1 ] ? 4533 initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : 4534 +valueParts[ 2 ]; 4535 if ( tween ) { 4536 tween.unit = unit; 4537 tween.start = initialInUnit; 4538 tween.end = adjusted; 4539 } 4540 } 4541 return adjusted; 4542} 4543 4544 4545var defaultDisplayMap = {}; 4546 4547function getDefaultDisplay( elem ) { 4548 var temp, 4549 doc = elem.ownerDocument, 4550 nodeName = elem.nodeName, 4551 display = defaultDisplayMap[ nodeName ]; 4552 4553 if ( display ) { 4554 return display; 4555 } 4556 4557 temp = doc.body.appendChild( doc.createElement( nodeName ) ); 4558 display = jQuery.css( temp, "display" ); 4559 4560 temp.parentNode.removeChild( temp ); 4561 4562 if ( display === "none" ) { 4563 display = "block"; 4564 } 4565 defaultDisplayMap[ nodeName ] = display; 4566 4567 return display; 4568} 4569 4570function showHide( elements, show ) { 4571 var display, elem, 4572 values = [], 4573 index = 0, 4574 length = elements.length; 4575 4576 // Determine new display value for elements that need to change 4577 for ( ; index < length; index++ ) { 4578 elem = elements[ index ]; 4579 if ( !elem.style ) { 4580 continue; 4581 } 4582 4583 display = elem.style.display; 4584 if ( show ) { 4585 4586 // Since we force visibility upon cascade-hidden elements, an immediate (and slow) 4587 // check is required in this first loop unless we have a nonempty display value (either 4588 // inline or about-to-be-restored) 4589 if ( display === "none" ) { 4590 values[ index ] = dataPriv.get( elem, "display" ) || null; 4591 if ( !values[ index ] ) { 4592 elem.style.display = ""; 4593 } 4594 } 4595 if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { 4596 values[ index ] = getDefaultDisplay( elem ); 4597 } 4598 } else { 4599 if ( display !== "none" ) { 4600 values[ index ] = "none"; 4601 4602 // Remember what we're overwriting 4603 dataPriv.set( elem, "display", display ); 4604 } 4605 } 4606 } 4607 4608 // Set the display of the elements in a second loop to avoid constant reflow 4609 for ( index = 0; index < length; index++ ) { 4610 if ( values[ index ] != null ) { 4611 elements[ index ].style.display = values[ index ]; 4612 } 4613 } 4614 4615 return elements; 4616} 4617 4618jQuery.fn.extend( { 4619 show: function() { 4620 return showHide( this, true ); 4621 }, 4622 hide: function() { 4623 return showHide( this ); 4624 }, 4625 toggle: function( state ) { 4626 if ( typeof state === "boolean" ) { 4627 return state ? this.show() : this.hide(); 4628 } 4629 4630 return this.each( function() { 4631 if ( isHiddenWithinTree( this ) ) { 4632 jQuery( this ).show(); 4633 } else { 4634 jQuery( this ).hide(); 4635 } 4636 } ); 4637 } 4638} ); 4639var rcheckableType = ( /^(?:checkbox|radio)$/i ); 4640 4641var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); 4642 4643var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); 4644 4645 4646 4647( function() { 4648 var fragment = document.createDocumentFragment(), 4649 div = fragment.appendChild( document.createElement( "div" ) ), 4650 input = document.createElement( "input" ); 4651 4652 // Support: Android 4.0 - 4.3 only 4653 // Check state lost if the name is set (trac-11217) 4654 // Support: Windows Web Apps (WWA) 4655 // `name` and `type` must use .setAttribute for WWA (trac-14901) 4656 input.setAttribute( "type", "radio" ); 4657 input.setAttribute( "checked", "checked" ); 4658 input.setAttribute( "name", "t" ); 4659 4660 div.appendChild( input ); 4661 4662 // Support: Android <=4.1 only 4663 // Older WebKit doesn't clone checked state correctly in fragments 4664 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; 4665 4666 // Support: IE <=11 only 4667 // Make sure textarea (and checkbox) defaultValue is properly cloned 4668 div.innerHTML = "<textarea>x</textarea>"; 4669 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; 4670 4671 // Support: IE <=9 only 4672 // IE <=9 replaces <option> tags with their contents when inserted outside of 4673 // the select element. 4674 div.innerHTML = "<option></option>"; 4675 support.option = !!div.lastChild; 4676} )(); 4677 4678 4679// We have to close these tags to support XHTML (trac-13200) 4680var wrapMap = { 4681 4682 // XHTML parsers do not magically insert elements in the 4683 // same way that tag soup parsers do. So we cannot shorten 4684 // this by omitting <tbody> or other required elements. 4685 thead: [ 1, "<table>", "</table>" ], 4686 col: [ 2, "<table><colgroup>", "</colgroup></table>" ], 4687 tr: [ 2, "<table><tbody>", "</tbody></table>" ], 4688 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], 4689 4690 _default: [ 0, "", "" ] 4691}; 4692 4693wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; 4694wrapMap.th = wrapMap.td; 4695 4696// Support: IE <=9 only 4697if ( !support.option ) { 4698 wrapMap.optgroup = wrapMap.option = [ 1, "<select multiple='multiple'>", "</select>" ]; 4699} 4700 4701 4702function getAll( context, tag ) { 4703 4704 // Support: IE <=9 - 11 only 4705 // Use typeof to avoid zero-argument method invocation on host objects (trac-15151) 4706 var ret; 4707 4708 if ( typeof context.getElementsByTagName !== "undefined" ) { 4709 ret = context.getElementsByTagName( tag || "*" ); 4710 4711 } else if ( typeof context.querySelectorAll !== "undefined" ) { 4712 ret = context.querySelectorAll( tag || "*" ); 4713 4714 } else { 4715 ret = []; 4716 } 4717 4718 if ( tag === undefined || tag && nodeName( context, tag ) ) { 4719 return jQuery.merge( [ context ], ret ); 4720 } 4721 4722 return ret; 4723} 4724 4725 4726// Mark scripts as having already been evaluated 4727function setGlobalEval( elems, refElements ) { 4728 var i = 0, 4729 l = elems.length; 4730 4731 for ( ; i < l; i++ ) { 4732 dataPriv.set( 4733 elems[ i ], 4734 "globalEval", 4735 !refElements || dataPriv.get( refElements[ i ], "globalEval" ) 4736 ); 4737 } 4738} 4739 4740 4741var rhtml = /<|&#?\w+;/; 4742 4743function buildFragment( elems, context, scripts, selection, ignored ) { 4744 var elem, tmp, tag, wrap, attached, j, 4745 fragment = context.createDocumentFragment(), 4746 nodes = [], 4747 i = 0, 4748 l = elems.length; 4749 4750 for ( ; i < l; i++ ) { 4751 elem = elems[ i ]; 4752 4753 if ( elem || elem === 0 ) { 4754 4755 // Add nodes directly 4756 if ( toType( elem ) === "object" ) { 4757 4758 // Support: Android <=4.0 only, PhantomJS 1 only 4759 // push.apply(_, arraylike) throws on ancient WebKit 4760 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); 4761 4762 // Convert non-html into a text node 4763 } else if ( !rhtml.test( elem ) ) { 4764 nodes.push( context.createTextNode( elem ) ); 4765 4766 // Convert html into DOM nodes 4767 } else { 4768 tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); 4769 4770 // Deserialize a standard representation 4771 tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); 4772 wrap = wrapMap[ tag ] || wrapMap._default; 4773 tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; 4774 4775 // Descend through wrappers to the right content 4776 j = wrap[ 0 ]; 4777 while ( j-- ) { 4778 tmp = tmp.lastChild; 4779 } 4780 4781 // Support: Android <=4.0 only, PhantomJS 1 only 4782 // push.apply(_, arraylike) throws on ancient WebKit 4783 jQuery.merge( nodes, tmp.childNodes ); 4784 4785 // Remember the top-level container 4786 tmp = fragment.firstChild; 4787 4788 // Ensure the created nodes are orphaned (trac-12392) 4789 tmp.textContent = ""; 4790 } 4791 } 4792 } 4793 4794 // Remove wrapper from fragment 4795 fragment.textContent = ""; 4796 4797 i = 0; 4798 while ( ( elem = nodes[ i++ ] ) ) { 4799 4800 // Skip elements already in the context collection (trac-4087) 4801 if ( selection && jQuery.inArray( elem, selection ) > -1 ) { 4802 if ( ignored ) { 4803 ignored.push( elem ); 4804 } 4805 continue; 4806 } 4807 4808 attached = isAttached( elem ); 4809 4810 // Append to fragment 4811 tmp = getAll( fragment.appendChild( elem ), "script" ); 4812 4813 // Preserve script evaluation history 4814 if ( attached ) { 4815 setGlobalEval( tmp ); 4816 } 4817 4818 // Capture executables 4819 if ( scripts ) { 4820 j = 0; 4821 while ( ( elem = tmp[ j++ ] ) ) { 4822 if ( rscriptType.test( elem.type || "" ) ) { 4823 scripts.push( elem ); 4824 } 4825 } 4826 } 4827 } 4828 4829 return fragment; 4830} 4831 4832 4833var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; 4834 4835function returnTrue() { 4836 return true; 4837} 4838 4839function returnFalse() { 4840 return false; 4841} 4842 4843function on( elem, types, selector, data, fn, one ) { 4844 var origFn, type; 4845 4846 // Types can be a map of types/handlers 4847 if ( typeof types === "object" ) { 4848 4849 // ( types-Object, selector, data ) 4850 if ( typeof selector !== "string" ) { 4851 4852 // ( types-Object, data ) 4853 data = data || selector; 4854 selector = undefined; 4855 } 4856 for ( type in types ) { 4857 on( elem, type, selector, data, types[ type ], one ); 4858 } 4859 return elem; 4860 } 4861 4862 if ( data == null && fn == null ) { 4863 4864 // ( types, fn ) 4865 fn = selector; 4866 data = selector = undefined; 4867 } else if ( fn == null ) { 4868 if ( typeof selector === "string" ) { 4869 4870 // ( types, selector, fn ) 4871 fn = data; 4872 data = undefined; 4873 } else { 4874 4875 // ( types, data, fn ) 4876 fn = data; 4877 data = selector; 4878 selector = undefined; 4879 } 4880 } 4881 if ( fn === false ) { 4882 fn = returnFalse; 4883 } else if ( !fn ) { 4884 return elem; 4885 } 4886 4887 if ( one === 1 ) { 4888 origFn = fn; 4889 fn = function( event ) { 4890 4891 // Can use an empty set, since event contains the info 4892 jQuery().off( event ); 4893 return origFn.apply( this, arguments ); 4894 }; 4895 4896 // Use same guid so caller can remove using origFn 4897 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); 4898 } 4899 return elem.each( function() { 4900 jQuery.event.add( this, types, fn, data, selector ); 4901 } ); 4902} 4903 4904/* 4905 * Helper functions for managing events -- not part of the public interface. 4906 * Props to Dean Edwards' addEvent library for many of the ideas. 4907 */ 4908jQuery.event = { 4909 4910 global: {}, 4911 4912 add: function( elem, types, handler, data, selector ) { 4913 4914 var handleObjIn, eventHandle, tmp, 4915 events, t, handleObj, 4916 special, handlers, type, namespaces, origType, 4917 elemData = dataPriv.get( elem ); 4918 4919 // Only attach events to objects that accept data 4920 if ( !acceptData( elem ) ) { 4921 return; 4922 } 4923 4924 // Caller can pass in an object of custom data in lieu of the handler 4925 if ( handler.handler ) { 4926 handleObjIn = handler; 4927 handler = handleObjIn.handler; 4928 selector = handleObjIn.selector; 4929 } 4930 4931 // Ensure that invalid selectors throw exceptions at attach time 4932 // Evaluate against documentElement in case elem is a non-element node (e.g., document) 4933 if ( selector ) { 4934 jQuery.find.matchesSelector( documentElement, selector ); 4935 } 4936 4937 // Make sure that the handler has a unique ID, used to find/remove it later 4938 if ( !handler.guid ) { 4939 handler.guid = jQuery.guid++; 4940 } 4941 4942 // Init the element's event structure and main handler, if this is the first 4943 if ( !( events = elemData.events ) ) { 4944 events = elemData.events = Object.create( null ); 4945 } 4946 if ( !( eventHandle = elemData.handle ) ) { 4947 eventHandle = elemData.handle = function( e ) { 4948 4949 // Discard the second event of a jQuery.event.trigger() and 4950 // when an event is called after a page has unloaded 4951 return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? 4952 jQuery.event.dispatch.apply( elem, arguments ) : undefined; 4953 }; 4954 } 4955 4956 // Handle multiple events separated by a space 4957 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; 4958 t = types.length; 4959 while ( t-- ) { 4960 tmp = rtypenamespace.exec( types[ t ] ) || []; 4961 type = origType = tmp[ 1 ]; 4962 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); 4963 4964 // There *must* be a type, no attaching namespace-only handlers 4965 if ( !type ) { 4966 continue; 4967 } 4968 4969 // If event changes its type, use the special event handlers for the changed type 4970 special = jQuery.event.special[ type ] || {}; 4971 4972 // If selector defined, determine special event api type, otherwise given type 4973 type = ( selector ? special.delegateType : special.bindType ) || type; 4974 4975 // Update special based on newly reset type 4976 special = jQuery.event.special[ type ] || {}; 4977 4978 // handleObj is passed to all event handlers 4979 handleObj = jQuery.extend( { 4980 type: type, 4981 origType: origType, 4982 data: data, 4983 handler: handler, 4984 guid: handler.guid, 4985 selector: selector, 4986 needsContext: selector && jQuery.expr.match.needsContext.test( selector ), 4987 namespace: namespaces.join( "." ) 4988 }, handleObjIn ); 4989 4990 // Init the event handler queue if we're the first 4991 if ( !( handlers = events[ type ] ) ) { 4992 handlers = events[ type ] = []; 4993 handlers.delegateCount = 0; 4994 4995 // Only use addEventListener if the special events handler returns false 4996 if ( !special.setup || 4997 special.setup.call( elem, data, namespaces, eventHandle ) === false ) { 4998 4999 if ( elem.addEventListener ) { 5000 elem.addEventListener( type, eventHandle ); 5001 } 5002 } 5003 } 5004 5005 if ( special.add ) { 5006 special.add.call( elem, handleObj ); 5007 5008 if ( !handleObj.handler.guid ) { 5009 handleObj.handler.guid = handler.guid; 5010 } 5011 } 5012 5013 // Add to the element's handler list, delegates in front 5014 if ( selector ) { 5015 handlers.splice( handlers.delegateCount++, 0, handleObj ); 5016 } else { 5017 handlers.push( handleObj ); 5018 } 5019 5020 // Keep track of which events have ever been used, for event optimization 5021 jQuery.event.global[ type ] = true; 5022 } 5023 5024 }, 5025 5026 // Detach an event or set of events from an element 5027 remove: function( elem, types, handler, selector, mappedTypes ) { 5028 5029 var j, origCount, tmp, 5030 events, t, handleObj, 5031 special, handlers, type, namespaces, origType, 5032 elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); 5033 5034 if ( !elemData || !( events = elemData.events ) ) { 5035 return; 5036 } 5037
vendor: 4,336 bytes, lines 5038-5176
5038 // Once for each type.namespace in types; type may be omitted 5039 types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; 5040 t = types.length; 5041 while ( t-- ) { 5042 tmp = rtypenamespace.exec( types[ t ] ) || []; 5043 type = origType = tmp[ 1 ]; 5044 namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); 5045 5046 // Unbind all events (on this namespace, if provided) for the element 5047 if ( !type ) { 5048 for ( type in events ) { 5049 jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); 5050 } 5051 continue; 5052 } 5053 5054 special = jQuery.event.special[ type ] || {}; 5055 type = ( selector ? special.delegateType : special.bindType ) || type; 5056 handlers = events[ type ] || []; 5057 tmp = tmp[ 2 ] && 5058 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); 5059 5060 // Remove matching events 5061 origCount = j = handlers.length; 5062 while ( j-- ) { 5063 handleObj = handlers[ j ]; 5064 5065 if ( ( mappedTypes || origType === handleObj.origType ) && 5066 ( !handler || handler.guid === handleObj.guid ) && 5067 ( !tmp || tmp.test( handleObj.namespace ) ) && 5068 ( !selector || selector === handleObj.selector || 5069 selector === "**" && handleObj.selector ) ) { 5070 handlers.splice( j, 1 ); 5071 5072 if ( handleObj.selector ) { 5073 handlers.delegateCount--; 5074 } 5075 if ( special.remove ) { 5076 special.remove.call( elem, handleObj ); 5077 } 5078 } 5079 } 5080 5081 // Remove generic event handler if we removed something and no more handlers exist 5082 // (avoids potential for endless recursion during removal of special event handlers) 5083 if ( origCount && !handlers.length ) { 5084 if ( !special.teardown || 5085 special.teardown.call( elem, namespaces, elemData.handle ) === false ) { 5086 5087 jQuery.removeEvent( elem, type, elemData.handle ); 5088 } 5089 5090 delete events[ type ]; 5091 } 5092 } 5093 5094 // Remove data and the expando if it's no longer used 5095 if ( jQuery.isEmptyObject( events ) ) { 5096 dataPriv.remove( elem, "handle events" ); 5097 } 5098 }, 5099 5100 dispatch: function( nativeEvent ) { 5101 5102 var i, j, ret, matched, handleObj, handlerQueue, 5103 args = new Array( arguments.length ), 5104 5105 // Make a writable jQuery.Event from the native event object 5106 event = jQuery.event.fix( nativeEvent ), 5107 5108 handlers = ( 5109 dataPriv.get( this, "events" ) || Object.create( null ) 5110 )[ event.type ] || [], 5111 special = jQuery.event.special[ event.type ] || {}; 5112 5113 // Use the fix-ed jQuery.Event rather than the (read-only) native event 5114 args[ 0 ] = event; 5115 5116 for ( i = 1; i < arguments.length; i++ ) { 5117 args[ i ] = arguments[ i ]; 5118 } 5119 5120 event.delegateTarget = this; 5121 5122 // Call the preDispatch hook for the mapped type, and let it bail if desired 5123 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { 5124 return; 5125 } 5126 5127 // Determine handlers 5128 handlerQueue = jQuery.event.handlers.call( this, event, handlers ); 5129 5130 // Run delegates first; they may want to stop propagation beneath us 5131 i = 0; 5132 while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { 5133 event.currentTarget = matched.elem; 5134 5135 j = 0; 5136 while ( ( handleObj = matched.handlers[ j++ ] ) && 5137 !event.isImmediatePropagationStopped() ) { 5138 5139 // If the event is namespaced, then each handler is only invoked if it is 5140 // specially universal or its namespaces are a superset of the event's. 5141 if ( !event.rnamespace || handleObj.namespace === false || 5142 event.rnamespace.test( handleObj.namespace ) ) { 5143 5144 event.handleObj = handleObj; 5145 event.data = handleObj.data; 5146 5147 ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || 5148 handleObj.handler ).apply( matched.elem, args ); 5149 5150 if ( ret !== undefined ) { 5151 if ( ( event.result = ret ) === false ) { 5152 event.preventDefault(); 5153 event.stopPropagation(); 5154 } 5155 } 5156 } 5157 } 5158 } 5159 5160 // Call the postDispatch hook for the mapped type 5161 if ( special.postDispatch ) { 5162 special.postDispatch.call( this, event ); 5163 } 5164 5165 return event.result; 5166 }, 5167 5168 handlers: function( event, handlers ) { 5169 var i, handleObj, sel, matchedHandlers, matchedSelectors, 5170 handlerQueue = [], 5171 delegateCount = handlers.delegateCount, 5172 cur = event.target; 5173 5174 // Find delegate handlers 5175 if ( delegateCount && 5176
vendor: 26,293 bytes, lines 5177-6053
5177 // Support: IE <=9 5178 // Black-hole SVG <use> instance trees (trac-13180) 5179 cur.nodeType && 5180 5181 // Support: Firefox <=42 5182 // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) 5183 // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click 5184 // Support: IE 11 only 5185 // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) 5186 !( event.type === "click" && event.button >= 1 ) ) { 5187 5188 for ( ; cur !== this; cur = cur.parentNode || this ) { 5189 5190 // Don't check non-elements (trac-13208) 5191 // Don't process clicks on disabled elements (trac-6911, trac-8165, trac-11382, trac-11764) 5192 if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { 5193 matchedHandlers = []; 5194 matchedSelectors = {}; 5195 for ( i = 0; i < delegateCount; i++ ) { 5196 handleObj = handlers[ i ]; 5197 5198 // Don't conflict with Object.prototype properties (trac-13203) 5199 sel = handleObj.selector + " "; 5200 5201 if ( matchedSelectors[ sel ] === undefined ) { 5202 matchedSelectors[ sel ] = handleObj.needsContext ? 5203 jQuery( sel, this ).index( cur ) > -1 : 5204 jQuery.find( sel, this, null, [ cur ] ).length; 5205 } 5206 if ( matchedSelectors[ sel ] ) { 5207 matchedHandlers.push( handleObj ); 5208 } 5209 } 5210 if ( matchedHandlers.length ) { 5211 handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); 5212 } 5213 } 5214 } 5215 } 5216 5217 // Add the remaining (directly-bound) handlers 5218 cur = this; 5219 if ( delegateCount < handlers.length ) { 5220 handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); 5221 } 5222 5223 return handlerQueue; 5224 }, 5225 5226 addProp: function( name, hook ) { 5227 Object.defineProperty( jQuery.Event.prototype, name, { 5228 enumerable: true, 5229 configurable: true, 5230 5231 get: isFunction( hook ) ? 5232 function() { 5233 if ( this.originalEvent ) { 5234 return hook( this.originalEvent ); 5235 } 5236 } : 5237 function() { 5238 if ( this.originalEvent ) { 5239 return this.originalEvent[ name ]; 5240 } 5241 }, 5242 5243 set: function( value ) { 5244 Object.defineProperty( this, name, { 5245 enumerable: true, 5246 configurable: true, 5247 writable: true, 5248 value: value 5249 } ); 5250 } 5251 } ); 5252 }, 5253 5254 fix: function( originalEvent ) { 5255 return originalEvent[ jQuery.expando ] ? 5256 originalEvent : 5257 new jQuery.Event( originalEvent ); 5258 }, 5259 5260 special: { 5261 load: { 5262 5263 // Prevent triggered image.load events from bubbling to window.load 5264 noBubble: true 5265 }, 5266 click: { 5267 5268 // Utilize native event to ensure correct state for checkable inputs 5269 setup: function( data ) { 5270 5271 // For mutual compressibility with _default, replace `this` access with a local var. 5272 // `|| data` is dead code meant only to preserve the variable through minification. 5273 var el = this || data; 5274 5275 // Claim the first handler 5276 if ( rcheckableType.test( el.type ) && 5277 el.click && nodeName( el, "input" ) ) { 5278 5279 // dataPriv.set( el, "click", ... ) 5280 leverageNative( el, "click", true ); 5281 } 5282 5283 // Return false to allow normal processing in the caller 5284 return false; 5285 }, 5286 trigger: function( data ) { 5287 5288 // For mutual compressibility with _default, replace `this` access with a local var. 5289 // `|| data` is dead code meant only to preserve the variable through minification. 5290 var el = this || data; 5291 5292 // Force setup before triggering a click 5293 if ( rcheckableType.test( el.type ) && 5294 el.click && nodeName( el, "input" ) ) { 5295 5296 leverageNative( el, "click" ); 5297 } 5298 5299 // Return non-false to allow normal event-path propagation 5300 return true; 5301 }, 5302 5303 // For cross-browser consistency, suppress native .click() on links 5304 // Also prevent it if we're currently inside a leveraged native-event stack 5305 _default: function( event ) { 5306 var target = event.target; 5307 return rcheckableType.test( target.type ) && 5308 target.click && nodeName( target, "input" ) && 5309 dataPriv.get( target, "click" ) || 5310 nodeName( target, "a" ); 5311 } 5312 }, 5313 5314 beforeunload: { 5315 postDispatch: function( event ) { 5316 5317 // Support: Firefox 20+ 5318 // Firefox doesn't alert if the returnValue field is not set. 5319 if ( event.result !== undefined && event.originalEvent ) { 5320 event.originalEvent.returnValue = event.result; 5321 } 5322 } 5323 } 5324 } 5325}; 5326 5327// Ensure the presence of an event listener that handles manually-triggered 5328// synthetic events by interrupting progress until reinvoked in response to 5329// *native* events that it fires directly, ensuring that state changes have 5330// already occurred before other listeners are invoked. 5331function leverageNative( el, type, isSetup ) { 5332 5333 // Missing `isSetup` indicates a trigger call, which must force setup through jQuery.event.add 5334 if ( !isSetup ) { 5335 if ( dataPriv.get( el, type ) === undefined ) { 5336 jQuery.event.add( el, type, returnTrue ); 5337 } 5338 return; 5339 } 5340 5341 // Register the controller as a special universal handler for all event namespaces 5342 dataPriv.set( el, type, false ); 5343 jQuery.event.add( el, type, { 5344 namespace: false, 5345 handler: function( event ) { 5346 var result, 5347 saved = dataPriv.get( this, type ); 5348 5349 if ( ( event.isTrigger & 1 ) && this[ type ] ) { 5350 5351 // Interrupt processing of the outer synthetic .trigger()ed event 5352 if ( !saved ) { 5353 5354 // Store arguments for use when handling the inner native event 5355 // There will always be at least one argument (an event object), so this array 5356 // will not be confused with a leftover capture object. 5357 saved = slice.call( arguments ); 5358 dataPriv.set( this, type, saved ); 5359 5360 // Trigger the native event and capture its result 5361 this[ type ](); 5362 result = dataPriv.get( this, type ); 5363 dataPriv.set( this, type, false ); 5364 5365 if ( saved !== result ) { 5366 5367 // Cancel the outer synthetic event 5368 event.stopImmediatePropagation(); 5369 event.preventDefault(); 5370 5371 return result; 5372 } 5373 5374 // If this is an inner synthetic event for an event with a bubbling surrogate 5375 // (focus or blur), assume that the surrogate already propagated from triggering 5376 // the native event and prevent that from happening again here. 5377 // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the 5378 // bubbling surrogate propagates *after* the non-bubbling base), but that seems 5379 // less bad than duplication. 5380 } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { 5381 event.stopPropagation(); 5382 } 5383 5384 // If this is a native event triggered above, everything is now in order 5385 // Fire an inner synthetic event with the original arguments 5386 } else if ( saved ) { 5387 5388 // ...and capture the result 5389 dataPriv.set( this, type, jQuery.event.trigger( 5390 saved[ 0 ], 5391 saved.slice( 1 ), 5392 this 5393 ) ); 5394 5395 // Abort handling of the native event by all jQuery handlers while allowing 5396 // native handlers on the same element to run. On target, this is achieved 5397 // by stopping immediate propagation just on the jQuery event. However, 5398 // the native event is re-wrapped by a jQuery one on each level of the 5399 // propagation so the only way to stop it for jQuery is to stop it for 5400 // everyone via native `stopPropagation()`. This is not a problem for 5401 // focus/blur which don't bubble, but it does also stop click on checkboxes 5402 // and radios. We accept this limitation. 5403 event.stopPropagation(); 5404 event.isImmediatePropagationStopped = returnTrue; 5405 } 5406 } 5407 } ); 5408} 5409 5410jQuery.removeEvent = function( elem, type, handle ) { 5411 5412 // This "if" is needed for plain objects 5413 if ( elem.removeEventListener ) { 5414 elem.removeEventListener( type, handle ); 5415 } 5416}; 5417 5418jQuery.Event = function( src, props ) { 5419 5420 // Allow instantiation without the 'new' keyword 5421 if ( !( this instanceof jQuery.Event ) ) { 5422 return new jQuery.Event( src, props ); 5423 } 5424 5425 // Event object 5426 if ( src && src.type ) { 5427 this.originalEvent = src; 5428 this.type = src.type; 5429 5430 // Events bubbling up the document may have been marked as prevented 5431 // by a handler lower down the tree; reflect the correct value. 5432 this.isDefaultPrevented = src.defaultPrevented || 5433 src.defaultPrevented === undefined && 5434 5435 // Support: Android <=2.3 only 5436 src.returnValue === false ? 5437 returnTrue : 5438 returnFalse; 5439 5440 // Create target properties 5441 // Support: Safari <=6 - 7 only 5442 // Target should not be a text node (trac-504, trac-13143) 5443 this.target = ( src.target && src.target.nodeType === 3 ) ? 5444 src.target.parentNode : 5445 src.target; 5446 5447 this.currentTarget = src.currentTarget; 5448 this.relatedTarget = src.relatedTarget; 5449 5450 // Event type 5451 } else { 5452 this.type = src; 5453 } 5454 5455 // Put explicitly provided properties onto the event object 5456 if ( props ) { 5457 jQuery.extend( this, props ); 5458 } 5459 5460 // Create a timestamp if incoming event doesn't have one 5461 this.timeStamp = src && src.timeStamp || Date.now(); 5462 5463 // Mark it as fixed 5464 this[ jQuery.expando ] = true; 5465}; 5466 5467// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding 5468// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 5469jQuery.Event.prototype = { 5470 constructor: jQuery.Event, 5471 isDefaultPrevented: returnFalse, 5472 isPropagationStopped: returnFalse, 5473 isImmediatePropagationStopped: returnFalse, 5474 isSimulated: false, 5475 5476 preventDefault: function() { 5477 var e = this.originalEvent; 5478 5479 this.isDefaultPrevented = returnTrue; 5480 5481 if ( e && !this.isSimulated ) { 5482 e.preventDefault(); 5483 } 5484 }, 5485 stopPropagation: function() { 5486 var e = this.originalEvent; 5487 5488 this.isPropagationStopped = returnTrue; 5489 5490 if ( e && !this.isSimulated ) { 5491 e.stopPropagation(); 5492 } 5493 }, 5494 stopImmediatePropagation: function() { 5495 var e = this.originalEvent; 5496 5497 this.isImmediatePropagationStopped = returnTrue; 5498 5499 if ( e && !this.isSimulated ) { 5500 e.stopImmediatePropagation(); 5501 } 5502 5503 this.stopPropagation(); 5504 } 5505}; 5506 5507// Includes all common event props including KeyEvent and MouseEvent specific props 5508jQuery.each( { 5509 altKey: true, 5510 bubbles: true, 5511 cancelable: true, 5512 changedTouches: true, 5513 ctrlKey: true, 5514 detail: true, 5515 eventPhase: true, 5516 metaKey: true, 5517 pageX: true, 5518 pageY: true, 5519 shiftKey: true, 5520 view: true, 5521 "char": true, 5522 code: true, 5523 charCode: true, 5524 key: true, 5525 keyCode: true, 5526 button: true, 5527 buttons: true, 5528 clientX: true, 5529 clientY: true, 5530 offsetX: true, 5531 offsetY: true, 5532 pointerId: true, 5533 pointerType: true, 5534 screenX: true, 5535 screenY: true, 5536 targetTouches: true, 5537 toElement: true, 5538 touches: true, 5539 which: true 5540}, jQuery.event.addProp ); 5541 5542jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { 5543 5544 function focusMappedHandler( nativeEvent ) { 5545 if ( document.documentMode ) { 5546 5547 // Support: IE 11+ 5548 // Attach a single focusin/focusout handler on the document while someone wants 5549 // focus/blur. This is because the former are synchronous in IE while the latter 5550 // are async. In other browsers, all those handlers are invoked synchronously. 5551 5552 // `handle` from private data would already wrap the event, but we need 5553 // to change the `type` here. 5554 var handle = dataPriv.get( this, "handle" ), 5555 event = jQuery.event.fix( nativeEvent ); 5556 event.type = nativeEvent.type === "focusin" ? "focus" : "blur"; 5557 event.isSimulated = true; 5558 5559 // First, handle focusin/focusout 5560 handle( nativeEvent ); 5561 5562 // ...then, handle focus/blur 5563 // 5564 // focus/blur don't bubble while focusin/focusout do; simulate the former by only 5565 // invoking the handler at the lower level. 5566 if ( event.target === event.currentTarget ) { 5567 5568 // The setup part calls `leverageNative`, which, in turn, calls 5569 // `jQuery.event.add`, so event handle will already have been set 5570 // by this point. 5571 handle( event ); 5572 } 5573 } else { 5574 5575 // For non-IE browsers, attach a single capturing handler on the document 5576 // while someone wants focusin/focusout. 5577 jQuery.event.simulate( delegateType, nativeEvent.target, 5578 jQuery.event.fix( nativeEvent ) ); 5579 } 5580 } 5581 5582 jQuery.event.special[ type ] = { 5583 5584 // Utilize native event if possible so blur/focus sequence is correct 5585 setup: function() { 5586 5587 var attaches; 5588 5589 // Claim the first handler 5590 // dataPriv.set( this, "focus", ... ) 5591 // dataPriv.set( this, "blur", ... ) 5592 leverageNative( this, type, true ); 5593 5594 if ( document.documentMode ) { 5595 5596 // Support: IE 9 - 11+ 5597 // We use the same native handler for focusin & focus (and focusout & blur) 5598 // so we need to coordinate setup & teardown parts between those events. 5599 // Use `delegateType` as the key as `type` is already used by `leverageNative`. 5600 attaches = dataPriv.get( this, delegateType ); 5601 if ( !attaches ) { 5602 this.addEventListener( delegateType, focusMappedHandler ); 5603 } 5604 dataPriv.set( this, delegateType, ( attaches || 0 ) + 1 ); 5605 } else { 5606 5607 // Return false to allow normal processing in the caller 5608 return false; 5609 } 5610 }, 5611 trigger: function() { 5612 5613 // Force setup before trigger 5614 leverageNative( this, type ); 5615 5616 // Return non-false to allow normal event-path propagation 5617 return true; 5618 }, 5619 5620 teardown: function() { 5621 var attaches; 5622 5623 if ( document.documentMode ) { 5624 attaches = dataPriv.get( this, delegateType ) - 1; 5625 if ( !attaches ) { 5626 this.removeEventListener( delegateType, focusMappedHandler ); 5627 dataPriv.remove( this, delegateType ); 5628 } else { 5629 dataPriv.set( this, delegateType, attaches ); 5630 } 5631 } else { 5632 5633 // Return false to indicate standard teardown should be applied 5634 return false; 5635 } 5636 }, 5637 5638 // Suppress native focus or blur if we're currently inside 5639 // a leveraged native-event stack 5640 _default: function( event ) { 5641 return dataPriv.get( event.target, type ); 5642 }, 5643 5644 delegateType: delegateType 5645 }; 5646 5647 // Support: Firefox <=44 5648 // Firefox doesn't have focus(in | out) events 5649 // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 5650 // 5651 // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 5652 // focus(in | out) events fire after focus & blur events, 5653 // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order 5654 // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 5655 // 5656 // Support: IE 9 - 11+ 5657 // To preserve relative focusin/focus & focusout/blur event order guaranteed on the 3.x branch, 5658 // attach a single handler for both events in IE. 5659 jQuery.event.special[ delegateType ] = { 5660 setup: function() { 5661 5662 // Handle: regular nodes (via `this.ownerDocument`), window 5663 // (via `this.document`) & document (via `this`). 5664 var doc = this.ownerDocument || this.document || this, 5665 dataHolder = document.documentMode ? this : doc, 5666 attaches = dataPriv.get( dataHolder, delegateType ); 5667 5668 // Support: IE 9 - 11+ 5669 // We use the same native handler for focusin & focus (and focusout & blur) 5670 // so we need to coordinate setup & teardown parts between those events. 5671 // Use `delegateType` as the key as `type` is already used by `leverageNative`. 5672 if ( !attaches ) { 5673 if ( document.documentMode ) { 5674 this.addEventListener( delegateType, focusMappedHandler ); 5675 } else { 5676 doc.addEventListener( type, focusMappedHandler, true ); 5677 } 5678 } 5679 dataPriv.set( dataHolder, delegateType, ( attaches || 0 ) + 1 ); 5680 }, 5681 teardown: function() { 5682 var doc = this.ownerDocument || this.document || this, 5683 dataHolder = document.documentMode ? this : doc, 5684 attaches = dataPriv.get( dataHolder, delegateType ) - 1; 5685 5686 if ( !attaches ) { 5687 if ( document.documentMode ) { 5688 this.removeEventListener( delegateType, focusMappedHandler ); 5689 } else { 5690 doc.removeEventListener( type, focusMappedHandler, true ); 5691 } 5692 dataPriv.remove( dataHolder, delegateType ); 5693 } else { 5694 dataPriv.set( dataHolder, delegateType, attaches ); 5695 } 5696 } 5697 }; 5698} ); 5699 5700// Create mouseenter/leave events using mouseover/out and event-time checks 5701// so that event delegation works in jQuery. 5702// Do the same for pointerenter/pointerleave and pointerover/pointerout 5703// 5704// Support: Safari 7 only 5705// Safari sends mouseenter too often; see: 5706// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 5707// for the description of the bug (it existed in older Chrome versions as well). 5708jQuery.each( { 5709 mouseenter: "mouseover", 5710 mouseleave: "mouseout", 5711 pointerenter: "pointerover", 5712 pointerleave: "pointerout" 5713}, function( orig, fix ) { 5714 jQuery.event.special[ orig ] = { 5715 delegateType: fix, 5716 bindType: fix, 5717 5718 handle: function( event ) { 5719 var ret, 5720 target = this, 5721 related = event.relatedTarget, 5722 handleObj = event.handleObj; 5723 5724 // For mouseenter/leave call the handler if related is outside the target. 5725 // NB: No relatedTarget if the mouse left/entered the browser window 5726 if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { 5727 event.type = handleObj.origType; 5728 ret = handleObj.handler.apply( this, arguments ); 5729 event.type = fix; 5730 } 5731 return ret; 5732 } 5733 }; 5734} ); 5735 5736jQuery.fn.extend( { 5737 5738 on: function( types, selector, data, fn ) { 5739 return on( this, types, selector, data, fn ); 5740 }, 5741 one: function( types, selector, data, fn ) { 5742 return on( this, types, selector, data, fn, 1 ); 5743 }, 5744 off: function( types, selector, fn ) { 5745 var handleObj, type; 5746 if ( types && types.preventDefault && types.handleObj ) { 5747 5748 // ( event ) dispatched jQuery.Event 5749 handleObj = types.handleObj; 5750 jQuery( types.delegateTarget ).off( 5751 handleObj.namespace ? 5752 handleObj.origType + "." + handleObj.namespace : 5753 handleObj.origType, 5754 handleObj.selector, 5755 handleObj.handler 5756 ); 5757 return this; 5758 } 5759 if ( typeof types === "object" ) { 5760 5761 // ( types-object [, selector] ) 5762 for ( type in types ) { 5763 this.off( type, selector, types[ type ] ); 5764 } 5765 return this; 5766 } 5767 if ( selector === false || typeof selector === "function" ) { 5768 5769 // ( types [, fn] ) 5770 fn = selector; 5771 selector = undefined; 5772 } 5773 if ( fn === false ) { 5774 fn = returnFalse; 5775 } 5776 return this.each( function() { 5777 jQuery.event.remove( this, types, fn, selector ); 5778 } ); 5779 } 5780} ); 5781 5782 5783var 5784 5785 // Support: IE <=10 - 11, Edge 12 - 13 only 5786 // In IE/Edge using regex groups here causes severe slowdowns. 5787 // See https://connect.microsoft.com/IE/feedback/details/1736512/ 5788 rnoInnerhtml = /<script|<style|<link/i, 5789 5790 // checked="checked" or checked 5791 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, 5792 5793 rcleanScript = /^\s*<!\[CDATA\[|\]\]>\s*$/g; 5794 5795// Prefer a tbody over its parent table for containing new rows 5796function manipulationTarget( elem, content ) { 5797 if ( nodeName( elem, "table" ) && 5798 nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { 5799 5800 return jQuery( elem ).children( "tbody" )[ 0 ] || elem; 5801 } 5802 5803 return elem; 5804} 5805 5806// Replace/restore the type attribute of script elements for safe DOM manipulation 5807function disableScript( elem ) { 5808 elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; 5809 return elem; 5810} 5811function restoreScript( elem ) { 5812 if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { 5813 elem.type = elem.type.slice( 5 ); 5814 } else { 5815 elem.removeAttribute( "type" ); 5816 } 5817 5818 return elem; 5819} 5820 5821function cloneCopyEvent( src, dest ) { 5822 var i, l, type, pdataOld, udataOld, udataCur, events; 5823 5824 if ( dest.nodeType !== 1 ) { 5825 return; 5826 } 5827 5828 // 1. Copy private data: events, handlers, etc. 5829 if ( dataPriv.hasData( src ) ) { 5830 pdataOld = dataPriv.get( src ); 5831 events = pdataOld.events; 5832 5833 if ( events ) { 5834 dataPriv.remove( dest, "handle events" ); 5835 5836 for ( type in events ) { 5837 for ( i = 0, l = events[ type ].length; i < l; i++ ) { 5838 jQuery.event.add( dest, type, events[ type ][ i ] ); 5839 } 5840 } 5841 } 5842 } 5843 5844 // 2. Copy user data 5845 if ( dataUser.hasData( src ) ) { 5846 udataOld = dataUser.access( src ); 5847 udataCur = jQuery.extend( {}, udataOld ); 5848 5849 dataUser.set( dest, udataCur ); 5850 } 5851} 5852 5853// Fix IE bugs, see support tests 5854function fixInput( src, dest ) { 5855 var nodeName = dest.nodeName.toLowerCase(); 5856 5857 // Fails to persist the checked state of a cloned checkbox or radio button. 5858 if ( nodeName === "input" && rcheckableType.test( src.type ) ) { 5859 dest.checked = src.checked; 5860 5861 // Fails to return the selected option to the default selected state when cloning options 5862 } else if ( nodeName === "input" || nodeName === "textarea" ) { 5863 dest.defaultValue = src.defaultValue; 5864 } 5865} 5866 5867function domManip( collection, args, callback, ignored ) { 5868 5869 // Flatten any nested arrays 5870 args = flat( args ); 5871 5872 var fragment, first, scripts, hasScripts, node, doc, 5873 i = 0, 5874 l = collection.length, 5875 iNoClone = l - 1, 5876 value = args[ 0 ], 5877 valueIsFunction = isFunction( value ); 5878 5879 // We can't cloneNode fragments that contain checked, in WebKit 5880 if ( valueIsFunction || 5881 ( l > 1 && typeof value === "string" && 5882 !support.checkClone && rchecked.test( value ) ) ) { 5883 return collection.each( function( index ) { 5884 var self = collection.eq( index ); 5885 if ( valueIsFunction ) { 5886 args[ 0 ] = value.call( this, index, self.html() ); 5887 } 5888 domManip( self, args, callback, ignored ); 5889 } ); 5890 } 5891 5892 if ( l ) { 5893 fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); 5894 first = fragment.firstChild; 5895 5896 if ( fragment.childNodes.length === 1 ) { 5897 fragment = first; 5898 } 5899 5900 // Require either new content or an interest in ignored elements to invoke the callback 5901 if ( first || ignored ) { 5902 scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); 5903 hasScripts = scripts.length; 5904 5905 // Use the original fragment for the last item 5906 // instead of the first because it can end up 5907 // being emptied incorrectly in certain situations (trac-8070). 5908 for ( ; i < l; i++ ) { 5909 node = fragment; 5910 5911 if ( i !== iNoClone ) { 5912 node = jQuery.clone( node, true, true ); 5913 5914 // Keep references to cloned scripts for later restoration 5915 if ( hasScripts ) { 5916 5917 // Support: Android <=4.0 only, PhantomJS 1 only 5918 // push.apply(_, arraylike) throws on ancient WebKit 5919 jQuery.merge( scripts, getAll( node, "script" ) ); 5920 } 5921 } 5922 5923 callback.call( collection[ i ], node, i ); 5924 } 5925 5926 if ( hasScripts ) { 5927 doc = scripts[ scripts.length - 1 ].ownerDocument; 5928 5929 // Re-enable scripts 5930 jQuery.map( scripts, restoreScript ); 5931 5932 // Evaluate executable scripts on first document insertion 5933 for ( i = 0; i < hasScripts; i++ ) { 5934 node = scripts[ i ]; 5935 if ( rscriptType.test( node.type || "" ) && 5936 !dataPriv.access( node, "globalEval" ) && 5937 jQuery.contains( doc, node ) ) { 5938 5939 if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { 5940 5941 // Optional AJAX dependency, but won't run scripts if not present 5942 if ( jQuery._evalUrl && !node.noModule ) { 5943 jQuery._evalUrl( node.src, { 5944 nonce: node.nonce || node.getAttribute( "nonce" ) 5945 }, doc ); 5946 } 5947 } else { 5948 5949 // Unwrap a CDATA section containing script contents. This shouldn't be 5950 // needed as in XML documents they're already not visible when 5951 // inspecting element contents and in HTML documents they have no 5952 // meaning but we're preserving that logic for backwards compatibility. 5953 // This will be removed completely in 4.0. See gh-4904. 5954 DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); 5955 } 5956 } 5957 } 5958 } 5959 } 5960 } 5961 5962 return collection; 5963} 5964 5965function remove( elem, selector, keepData ) { 5966 var node, 5967 nodes = selector ? jQuery.filter( selector, elem ) : elem, 5968 i = 0; 5969 5970 for ( ; ( node = nodes[ i ] ) != null; i++ ) { 5971 if ( !keepData && node.nodeType === 1 ) { 5972 jQuery.cleanData( getAll( node ) ); 5973 } 5974 5975 if ( node.parentNode ) { 5976 if ( keepData && isAttached( node ) ) { 5977 setGlobalEval( getAll( node, "script" ) ); 5978 } 5979 node.parentNode.removeChild( node ); 5980 } 5981 } 5982 5983 return elem; 5984} 5985 5986jQuery.extend( { 5987 htmlPrefilter: function( html ) { 5988 return html; 5989 }, 5990 5991 clone: function( elem, dataAndEvents, deepDataAndEvents ) { 5992 var i, l, srcElements, destElements, 5993 clone = elem.cloneNode( true ), 5994 inPage = isAttached( elem ); 5995 5996 // Fix IE cloning issues 5997 if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && 5998 !jQuery.isXMLDoc( elem ) ) { 5999 6000 // We eschew jQuery#find here for performance reasons: 6001 // https://jsperf.com/getall-vs-sizzle/2 6002 destElements = getAll( clone ); 6003 srcElements = getAll( elem ); 6004 6005 for ( i = 0, l = srcElements.length; i < l; i++ ) { 6006 fixInput( srcElements[ i ], destElements[ i ] ); 6007 } 6008 } 6009 6010 // Copy the events from the original to the clone 6011 if ( dataAndEvents ) { 6012 if ( deepDataAndEvents ) { 6013 srcElements = srcElements || getAll( elem ); 6014 destElements = destElements || getAll( clone ); 6015 6016 for ( i = 0, l = srcElements.length; i < l; i++ ) { 6017 cloneCopyEvent( srcElements[ i ], destElements[ i ] ); 6018 } 6019 } else { 6020 cloneCopyEvent( elem, clone ); 6021 } 6022 } 6023 6024 // Preserve script evaluation history 6025 destElements = getAll( clone, "script" ); 6026 if ( destElements.length > 0 ) { 6027 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); 6028 } 6029 6030 // Return the cloned set 6031 return clone; 6032 }, 6033 6034 cleanData: function( elems ) { 6035 var data, elem, type, 6036 special = jQuery.event.special, 6037 i = 0; 6038 6039 for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { 6040 if ( acceptData( elem ) ) { 6041 if ( ( data = elem[ dataPriv.expando ] ) ) { 6042 if ( data.events ) { 6043 for ( type in data.events ) { 6044 if ( special[ type ] ) { 6045 jQuery.event.remove( elem, type ); 6046 6047 // This is a shortcut to avoid jQuery.event.remove's overhead 6048 } else { 6049 jQuery.removeEvent( elem, type, data.handle ); 6050 } 6051 } 6052 } 6053
vendor: 4,139 bytes, lines 6054-6218
6054 // Support: Chrome <=35 - 45+ 6055 // Assign undefined instead of using delete, see Data#remove 6056 elem[ dataPriv.expando ] = undefined; 6057 } 6058 if ( elem[ dataUser.expando ] ) { 6059 6060 // Support: Chrome <=35 - 45+ 6061 // Assign undefined instead of using delete, see Data#remove 6062 elem[ dataUser.expando ] = undefined; 6063 } 6064 } 6065 } 6066 } 6067} ); 6068 6069jQuery.fn.extend( { 6070 detach: function( selector ) { 6071 return remove( this, selector, true ); 6072 }, 6073 6074 remove: function( selector ) { 6075 return remove( this, selector ); 6076 }, 6077 6078 text: function( value ) { 6079 return access( this, function( value ) { 6080 return value === undefined ? 6081 jQuery.text( this ) : 6082 this.empty().each( function() { 6083 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 6084 this.textContent = value; 6085 } 6086 } ); 6087 }, null, value, arguments.length ); 6088 }, 6089 6090 append: function() { 6091 return domManip( this, arguments, function( elem ) { 6092 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 6093 var target = manipulationTarget( this, elem ); 6094 target.appendChild( elem ); 6095 } 6096 } ); 6097 }, 6098 6099 prepend: function() { 6100 return domManip( this, arguments, function( elem ) { 6101 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { 6102 var target = manipulationTarget( this, elem ); 6103 target.insertBefore( elem, target.firstChild ); 6104 } 6105 } ); 6106 }, 6107 6108 before: function() { 6109 return domManip( this, arguments, function( elem ) { 6110 if ( this.parentNode ) { 6111 this.parentNode.insertBefore( elem, this ); 6112 } 6113 } ); 6114 }, 6115 6116 after: function() { 6117 return domManip( this, arguments, function( elem ) { 6118 if ( this.parentNode ) { 6119 this.parentNode.insertBefore( elem, this.nextSibling ); 6120 } 6121 } ); 6122 }, 6123 6124 empty: function() { 6125 var elem, 6126 i = 0; 6127 6128 for ( ; ( elem = this[ i ] ) != null; i++ ) { 6129 if ( elem.nodeType === 1 ) { 6130 6131 // Prevent memory leaks 6132 jQuery.cleanData( getAll( elem, false ) ); 6133 6134 // Remove any remaining nodes 6135 elem.textContent = ""; 6136 } 6137 } 6138 6139 return this; 6140 }, 6141 6142 clone: function( dataAndEvents, deepDataAndEvents ) { 6143 dataAndEvents = dataAndEvents == null ? false : dataAndEvents; 6144 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; 6145 6146 return this.map( function() { 6147 return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); 6148 } ); 6149 }, 6150 6151 html: function( value ) { 6152 return access( this, function( value ) { 6153 var elem = this[ 0 ] || {}, 6154 i = 0, 6155 l = this.length; 6156 6157 if ( value === undefined && elem.nodeType === 1 ) { 6158 return elem.innerHTML; 6159 } 6160 6161 // See if we can take a shortcut and just use innerHTML 6162 if ( typeof value === "string" && !rnoInnerhtml.test( value ) && 6163 !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { 6164 6165 value = jQuery.htmlPrefilter( value ); 6166 6167 try { 6168 for ( ; i < l; i++ ) { 6169 elem = this[ i ] || {}; 6170 6171 // Remove element nodes and prevent memory leaks 6172 if ( elem.nodeType === 1 ) { 6173 jQuery.cleanData( getAll( elem, false ) ); 6174 elem.innerHTML = value; 6175 } 6176 } 6177 6178 elem = 0; 6179 6180 // If using innerHTML throws an exception, use the fallback method 6181 } catch ( e ) {} 6182 } 6183 6184 if ( elem ) { 6185 this.empty().append( value ); 6186 } 6187 }, null, value, arguments.length ); 6188 }, 6189 6190 replaceWith: function() { 6191 var ignored = []; 6192 6193 // Make the changes, replacing each non-ignored context element with the new content 6194 return domManip( this, arguments, function( elem ) { 6195 var parent = this.parentNode; 6196 6197 if ( jQuery.inArray( this, ignored ) < 0 ) { 6198 jQuery.cleanData( getAll( this ) ); 6199 if ( parent ) { 6200 parent.replaceChild( elem, this ); 6201 } 6202 } 6203 6204 // Force callback invocation 6205 }, ignored ); 6206 } 6207} ); 6208 6209jQuery.each( { 6210 appendTo: "append", 6211 prependTo: "prepend", 6212 insertBefore: "before", 6213 insertAfter: "after", 6214 replaceAll: "replaceWith" 6215}, function( name, original ) { 6216 jQuery.fn[ name ] = function( selector ) { 6217 var elems, 6218 ret = [],
vendor: 31,588 bytes, lines 6219-7281
6219 insert = jQuery( selector ), 6220 last = insert.length - 1, 6221 i = 0; 6222 6223 for ( ; i <= last; i++ ) { 6224 elems = i === last ? this : this.clone( true ); 6225 jQuery( insert[ i ] )[ original ]( elems ); 6226 6227 // Support: Android <=4.0 only, PhantomJS 1 only 6228 // .get() because push.apply(_, arraylike) throws on ancient WebKit 6229 push.apply( ret, elems.get() ); 6230 } 6231 6232 return this.pushStack( ret ); 6233 }; 6234} ); 6235var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); 6236 6237var rcustomProp = /^--/; 6238 6239 6240var getStyles = function( elem ) { 6241 6242 // Support: IE <=11 only, Firefox <=30 (trac-15098, trac-14150) 6243 // IE throws on elements created in popups 6244 // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" 6245 var view = elem.ownerDocument.defaultView; 6246 6247 if ( !view || !view.opener ) { 6248 view = window; 6249 } 6250 6251 return view.getComputedStyle( elem ); 6252 }; 6253 6254var swap = function( elem, options, callback ) { 6255 var ret, name, 6256 old = {}; 6257 6258 // Remember the old values, and insert the new ones 6259 for ( name in options ) { 6260 old[ name ] = elem.style[ name ]; 6261 elem.style[ name ] = options[ name ]; 6262 } 6263 6264 ret = callback.call( elem ); 6265 6266 // Revert the old values 6267 for ( name in options ) { 6268 elem.style[ name ] = old[ name ]; 6269 } 6270 6271 return ret; 6272}; 6273 6274 6275var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); 6276 6277 6278 6279( function() { 6280 6281 // Executing both pixelPosition & boxSizingReliable tests require only one layout 6282 // so they're executed at the same time to save the second computation. 6283 function computeStyleTests() { 6284 6285 // This is a singleton, we need to execute it only once 6286 if ( !div ) { 6287 return; 6288 } 6289 6290 container.style.cssText = "position:absolute;left:-11111px;width:60px;" + 6291 "margin-top:1px;padding:0;border:0"; 6292 div.style.cssText = 6293 "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + 6294 "margin:auto;border:1px;padding:1px;" + 6295 "width:60%;top:1%"; 6296 documentElement.appendChild( container ).appendChild( div ); 6297 6298 var divStyle = window.getComputedStyle( div ); 6299 pixelPositionVal = divStyle.top !== "1%"; 6300 6301 // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 6302 reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; 6303 6304 // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 6305 // Some styles come back with percentage values, even though they shouldn't 6306 div.style.right = "60%"; 6307 pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; 6308 6309 // Support: IE 9 - 11 only 6310 // Detect misreporting of content dimensions for box-sizing:border-box elements 6311 boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; 6312 6313 // Support: IE 9 only 6314 // Detect overflow:scroll screwiness (gh-3699) 6315 // Support: Chrome <=64 6316 // Don't get tricked when zoom affects offsetWidth (gh-4029) 6317 div.style.position = "absolute"; 6318 scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; 6319 6320 documentElement.removeChild( container ); 6321 6322 // Nullify the div so it wouldn't be stored in the memory and 6323 // it will also be a sign that checks already performed 6324 div = null; 6325 } 6326 6327 function roundPixelMeasures( measure ) { 6328 return Math.round( parseFloat( measure ) ); 6329 } 6330 6331 var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, 6332 reliableTrDimensionsVal, reliableMarginLeftVal, 6333 container = document.createElement( "div" ), 6334 div = document.createElement( "div" ); 6335 6336 // Finish early in limited (non-browser) environments 6337 if ( !div.style ) { 6338 return; 6339 } 6340 6341 // Support: IE <=9 - 11 only 6342 // Style of cloned element affects source element cloned (trac-8908) 6343 div.style.backgroundClip = "content-box"; 6344 div.cloneNode( true ).style.backgroundClip = ""; 6345 support.clearCloneStyle = div.style.backgroundClip === "content-box"; 6346 6347 jQuery.extend( support, { 6348 boxSizingReliable: function() { 6349 computeStyleTests(); 6350 return boxSizingReliableVal; 6351 }, 6352 pixelBoxStyles: function() { 6353 computeStyleTests(); 6354 return pixelBoxStylesVal; 6355 }, 6356 pixelPosition: function() { 6357 computeStyleTests(); 6358 return pixelPositionVal; 6359 }, 6360 reliableMarginLeft: function() { 6361 computeStyleTests(); 6362 return reliableMarginLeftVal; 6363 }, 6364 scrollboxSize: function() { 6365 computeStyleTests(); 6366 return scrollboxSizeVal; 6367 }, 6368 6369 // Support: IE 9 - 11+, Edge 15 - 18+ 6370 // IE/Edge misreport `getComputedStyle` of table rows with width/height 6371 // set in CSS while `offset*` properties report correct values. 6372 // Behavior in IE 9 is more subtle than in newer versions & it passes 6373 // some versions of this test; make sure not to make it pass there! 6374 // 6375 // Support: Firefox 70+ 6376 // Only Firefox includes border widths 6377 // in computed dimensions. (gh-4529) 6378 reliableTrDimensions: function() { 6379 var table, tr, trChild, trStyle; 6380 if ( reliableTrDimensionsVal == null ) { 6381 table = document.createElement( "table" ); 6382 tr = document.createElement( "tr" ); 6383 trChild = document.createElement( "div" ); 6384 6385 table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; 6386 tr.style.cssText = "box-sizing:content-box;border:1px solid"; 6387 6388 // Support: Chrome 86+ 6389 // Height set through cssText does not get applied. 6390 // Computed height then comes back as 0. 6391 tr.style.height = "1px"; 6392 trChild.style.height = "9px"; 6393 6394 // Support: Android 8 Chrome 86+ 6395 // In our bodyBackground.html iframe, 6396 // display for all div elements is set to "inline", 6397 // which causes a problem only in Android 8 Chrome 86. 6398 // Ensuring the div is `display: block` 6399 // gets around this issue. 6400 trChild.style.display = "block"; 6401 6402 documentElement 6403 .appendChild( table ) 6404 .appendChild( tr ) 6405 .appendChild( trChild ); 6406 6407 trStyle = window.getComputedStyle( tr ); 6408 reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + 6409 parseInt( trStyle.borderTopWidth, 10 ) + 6410 parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; 6411 6412 documentElement.removeChild( table ); 6413 } 6414 return reliableTrDimensionsVal; 6415 } 6416 } ); 6417} )(); 6418 6419 6420function curCSS( elem, name, computed ) { 6421 var width, minWidth, maxWidth, ret, 6422 isCustomProp = rcustomProp.test( name ), 6423 6424 // Support: Firefox 51+ 6425 // Retrieving style before computed somehow 6426 // fixes an issue with getting wrong values 6427 // on detached elements 6428 style = elem.style; 6429 6430 computed = computed || getStyles( elem ); 6431 6432 // getPropertyValue is needed for: 6433 // .css('filter') (IE 9 only, trac-12537) 6434 // .css('--customProperty) (gh-3144) 6435 if ( computed ) { 6436 6437 // Support: IE <=9 - 11+ 6438 // IE only supports `"float"` in `getPropertyValue`; in computed styles 6439 // it's only available as `"cssFloat"`. We no longer modify properties 6440 // sent to `.css()` apart from camelCasing, so we need to check both. 6441 // Normally, this would create difference in behavior: if 6442 // `getPropertyValue` returns an empty string, the value returned 6443 // by `.css()` would be `undefined`. This is usually the case for 6444 // disconnected elements. However, in IE even disconnected elements 6445 // with no styles return `"none"` for `getPropertyValue( "float" )` 6446 ret = computed.getPropertyValue( name ) || computed[ name ]; 6447 6448 if ( isCustomProp && ret ) { 6449 6450 // Support: Firefox 105+, Chrome <=105+ 6451 // Spec requires trimming whitespace for custom properties (gh-4926). 6452 // Firefox only trims leading whitespace. Chrome just collapses 6453 // both leading & trailing whitespace to a single space. 6454 // 6455 // Fall back to `undefined` if empty string returned. 6456 // This collapses a missing definition with property defined 6457 // and set to an empty string but there's no standard API 6458 // allowing us to differentiate them without a performance penalty 6459 // and returning `undefined` aligns with older jQuery. 6460 // 6461 // rtrimCSS treats U+000D CARRIAGE RETURN and U+000C FORM FEED 6462 // as whitespace while CSS does not, but this is not a problem 6463 // because CSS preprocessing replaces them with U+000A LINE FEED 6464 // (which *is* CSS whitespace) 6465 // https://www.w3.org/TR/css-syntax-3/#input-preprocessing 6466 ret = ret.replace( rtrimCSS, "$1" ) || undefined; 6467 } 6468 6469 if ( ret === "" && !isAttached( elem ) ) { 6470 ret = jQuery.style( elem, name ); 6471 } 6472 6473 // A tribute to the "awesome hack by Dean Edwards" 6474 // Android Browser returns percentage for some values, 6475 // but width seems to be reliably pixels. 6476 // This is against the CSSOM draft spec: 6477 // https://drafts.csswg.org/cssom/#resolved-values 6478 if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { 6479 6480 // Remember the original values 6481 width = style.width; 6482 minWidth = style.minWidth; 6483 maxWidth = style.maxWidth; 6484 6485 // Put in the new values to get a computed value out 6486 style.minWidth = style.maxWidth = style.width = ret; 6487 ret = computed.width; 6488 6489 // Revert the changed values 6490 style.width = width; 6491 style.minWidth = minWidth; 6492 style.maxWidth = maxWidth; 6493 } 6494 } 6495 6496 return ret !== undefined ? 6497 6498 // Support: IE <=9 - 11 only 6499 // IE returns zIndex value as an integer. 6500 ret + "" : 6501 ret; 6502} 6503 6504 6505function addGetHookIf( conditionFn, hookFn ) { 6506 6507 // Define the hook, we'll check on the first run if it's really needed. 6508 return { 6509 get: function() { 6510 if ( conditionFn() ) { 6511 6512 // Hook not needed (or it's not possible to use it due 6513 // to missing dependency), remove it. 6514 delete this.get; 6515 return; 6516 } 6517 6518 // Hook needed; redefine it so that the support test is not executed again. 6519 return ( this.get = hookFn ).apply( this, arguments ); 6520 } 6521 }; 6522} 6523 6524 6525var cssPrefixes = [ "Webkit", "Moz", "ms" ], 6526 emptyStyle = document.createElement( "div" ).style, 6527 vendorProps = {}; 6528 6529// Return a vendor-prefixed property or undefined 6530function vendorPropName( name ) { 6531 6532 // Check for vendor prefixed names 6533 var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), 6534 i = cssPrefixes.length; 6535 6536 while ( i-- ) { 6537 name = cssPrefixes[ i ] + capName; 6538 if ( name in emptyStyle ) { 6539 return name; 6540 } 6541 } 6542} 6543 6544// Return a potentially-mapped jQuery.cssProps or vendor prefixed property 6545function finalPropName( name ) { 6546 var final = jQuery.cssProps[ name ] || vendorProps[ name ]; 6547 6548 if ( final ) { 6549 return final; 6550 } 6551 if ( name in emptyStyle ) { 6552 return name; 6553 } 6554 return vendorProps[ name ] = vendorPropName( name ) || name; 6555} 6556 6557 6558var 6559 6560 // Swappable if display is none or starts with table 6561 // except "table", "table-cell", or "table-caption" 6562 // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display 6563 rdisplayswap = /^(none|table(?!-c[ea]).+)/, 6564 cssShow = { position: "absolute", visibility: "hidden", display: "block" }, 6565 cssNormalTransform = { 6566 letterSpacing: "0", 6567 fontWeight: "400" 6568 }; 6569 6570function setPositiveNumber( _elem, value, subtract ) { 6571 6572 // Any relative (+/-) values have already been 6573 // normalized at this point 6574 var matches = rcssNum.exec( value ); 6575 return matches ? 6576 6577 // Guard against undefined "subtract", e.g., when used as in cssHooks 6578 Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : 6579 value; 6580} 6581 6582function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { 6583 var i = dimension === "width" ? 1 : 0, 6584 extra = 0, 6585 delta = 0, 6586 marginDelta = 0; 6587 6588 // Adjustment may not be necessary 6589 if ( box === ( isBorderBox ? "border" : "content" ) ) { 6590 return 0; 6591 } 6592 6593 for ( ; i < 4; i += 2 ) { 6594 6595 // Both box models exclude margin 6596 // Count margin delta separately to only add it after scroll gutter adjustment. 6597 // This is needed to make negative margins work with `outerHeight( true )` (gh-3982). 6598 if ( box === "margin" ) { 6599 marginDelta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); 6600 } 6601 6602 // If we get here with a content-box, we're seeking "padding" or "border" or "margin" 6603 if ( !isBorderBox ) { 6604 6605 // Add padding 6606 delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 6607 6608 // For "border" or "margin", add border 6609 if ( box !== "padding" ) { 6610 delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 6611 6612 // But still keep track of it otherwise 6613 } else { 6614 extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 6615 } 6616 6617 // If we get here with a border-box (content + padding + border), we're seeking "content" or 6618 // "padding" or "margin" 6619 } else { 6620 6621 // For "content", subtract padding 6622 if ( box === "content" ) { 6623 delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); 6624 } 6625 6626 // For "content" or "padding", subtract border 6627 if ( box !== "margin" ) { 6628 delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); 6629 } 6630 } 6631 } 6632 6633 // Account for positive content-box scroll gutter when requested by providing computedVal 6634 if ( !isBorderBox && computedVal >= 0 ) { 6635 6636 // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border 6637 // Assuming integer scroll gutter, subtract the rest and round down 6638 delta += Math.max( 0, Math.ceil( 6639 elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - 6640 computedVal - 6641 delta - 6642 extra - 6643 0.5 6644 6645 // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter 6646 // Use an explicit zero to avoid NaN (gh-3964) 6647 ) ) || 0; 6648 } 6649 6650 return delta + marginDelta; 6651} 6652 6653function getWidthOrHeight( elem, dimension, extra ) { 6654 6655 // Start with computed style 6656 var styles = getStyles( elem ), 6657 6658 // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). 6659 // Fake content-box until we know it's needed to know the true value. 6660 boxSizingNeeded = !support.boxSizingReliable() || extra, 6661 isBorderBox = boxSizingNeeded && 6662 jQuery.css( elem, "boxSizing", false, styles ) === "border-box", 6663 valueIsBorderBox = isBorderBox, 6664 6665 val = curCSS( elem, dimension, styles ), 6666 offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); 6667 6668 // Support: Firefox <=54 6669 // Return a confounding non-pixel value or feign ignorance, as appropriate. 6670 if ( rnumnonpx.test( val ) ) { 6671 if ( !extra ) { 6672 return val; 6673 } 6674 val = "auto"; 6675 } 6676 6677 6678 // Support: IE 9 - 11 only 6679 // Use offsetWidth/offsetHeight for when box sizing is unreliable. 6680 // In those cases, the computed value can be trusted to be border-box. 6681 if ( ( !support.boxSizingReliable() && isBorderBox || 6682 6683 // Support: IE 10 - 11+, Edge 15 - 18+ 6684 // IE/Edge misreport `getComputedStyle` of table rows with width/height 6685 // set in CSS while `offset*` properties report correct values. 6686 // Interestingly, in some cases IE 9 doesn't suffer from this issue. 6687 !support.reliableTrDimensions() && nodeName( elem, "tr" ) || 6688 6689 // Fall back to offsetWidth/offsetHeight when value is "auto" 6690 // This happens for inline elements with no explicit setting (gh-3571) 6691 val === "auto" || 6692 6693 // Support: Android <=4.1 - 4.3 only 6694 // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) 6695 !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && 6696 6697 // Make sure the element is visible & connected 6698 elem.getClientRects().length ) { 6699 6700 isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; 6701 6702 // Where available, offsetWidth/offsetHeight approximate border box dimensions. 6703 // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the 6704 // retrieved value as a content box dimension. 6705 valueIsBorderBox = offsetProp in elem; 6706 if ( valueIsBorderBox ) { 6707 val = elem[ offsetProp ]; 6708 } 6709 } 6710 6711 // Normalize "" and auto 6712 val = parseFloat( val ) || 0; 6713 6714 // Adjust for the element's box model 6715 return ( val + 6716 boxModelAdjustment( 6717 elem, 6718 dimension, 6719 extra || ( isBorderBox ? "border" : "content" ), 6720 valueIsBorderBox, 6721 styles, 6722 6723 // Provide the current computed size to request scroll gutter calculation (gh-3589) 6724 val 6725 ) 6726 ) + "px"; 6727} 6728 6729jQuery.extend( { 6730 6731 // Add in style property hooks for overriding the default 6732 // behavior of getting and setting a style property 6733 cssHooks: { 6734 opacity: { 6735 get: function( elem, computed ) { 6736 if ( computed ) { 6737 6738 // We should always get a number back from opacity 6739 var ret = curCSS( elem, "opacity" ); 6740 return ret === "" ? "1" : ret; 6741 } 6742 } 6743 } 6744 }, 6745 6746 // Don't automatically add "px" to these possibly-unitless properties 6747 cssNumber: { 6748 animationIterationCount: true, 6749 aspectRatio: true, 6750 borderImageSlice: true, 6751 columnCount: true, 6752 flexGrow: true, 6753 flexShrink: true, 6754 fontWeight: true, 6755 gridArea: true, 6756 gridColumn: true, 6757 gridColumnEnd: true, 6758 gridColumnStart: true, 6759 gridRow: true, 6760 gridRowEnd: true, 6761 gridRowStart: true, 6762 lineHeight: true, 6763 opacity: true, 6764 order: true, 6765 orphans: true, 6766 scale: true, 6767 widows: true, 6768 zIndex: true, 6769 zoom: true, 6770 6771 // SVG-related 6772 fillOpacity: true, 6773 floodOpacity: true, 6774 stopOpacity: true, 6775 strokeMiterlimit: true, 6776 strokeOpacity: true 6777 }, 6778 6779 // Add in properties whose names you wish to fix before 6780 // setting or getting the value 6781 cssProps: {}, 6782 6783 // Get and set the style property on a DOM Node 6784 style: function( elem, name, value, extra ) { 6785 6786 // Don't set styles on text and comment nodes 6787 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { 6788 return; 6789 } 6790 6791 // Make sure that we're working with the right name 6792 var ret, type, hooks, 6793 origName = camelCase( name ), 6794 isCustomProp = rcustomProp.test( name ), 6795 style = elem.style; 6796 6797 // Make sure that we're working with the right name. We don't 6798 // want to query the value if it is a CSS custom property 6799 // since they are user-defined. 6800 if ( !isCustomProp ) { 6801 name = finalPropName( origName ); 6802 } 6803 6804 // Gets hook for the prefixed version, then unprefixed version 6805 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 6806 6807 // Check if we're setting a value 6808 if ( value !== undefined ) { 6809 type = typeof value; 6810 6811 // Convert "+=" or "-=" to relative numbers (trac-7345) 6812 if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { 6813 value = adjustCSS( elem, name, ret ); 6814 6815 // Fixes bug trac-9237 6816 type = "number"; 6817 } 6818 6819 // Make sure that null and NaN values aren't set (trac-7116) 6820 if ( value == null || value !== value ) { 6821 return; 6822 } 6823 6824 // If a number was passed in, add the unit (except for certain CSS properties) 6825 // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append 6826 // "px" to a few hardcoded values. 6827 if ( type === "number" && !isCustomProp ) { 6828 value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); 6829 } 6830 6831 // background-* props affect original clone's values 6832 if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { 6833 style[ name ] = "inherit"; 6834 } 6835 6836 // If a hook was provided, use that value, otherwise just set the specified value 6837 if ( !hooks || !( "set" in hooks ) || 6838 ( value = hooks.set( elem, value, extra ) ) !== undefined ) { 6839 6840 if ( isCustomProp ) { 6841 style.setProperty( name, value ); 6842 } else { 6843 style[ name ] = value; 6844 } 6845 } 6846 6847 } else { 6848 6849 // If a hook was provided get the non-computed value from there 6850 if ( hooks && "get" in hooks && 6851 ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { 6852 6853 return ret; 6854 } 6855 6856 // Otherwise just get the value from the style object 6857 return style[ name ]; 6858 } 6859 }, 6860 6861 css: function( elem, name, extra, styles ) { 6862 var val, num, hooks, 6863 origName = camelCase( name ), 6864 isCustomProp = rcustomProp.test( name ); 6865 6866 // Make sure that we're working with the right name. We don't 6867 // want to modify the value if it is a CSS custom property 6868 // since they are user-defined. 6869 if ( !isCustomProp ) { 6870 name = finalPropName( origName ); 6871 } 6872 6873 // Try prefixed name followed by the unprefixed name 6874 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; 6875 6876 // If a hook was provided get the computed value from there 6877 if ( hooks && "get" in hooks ) { 6878 val = hooks.get( elem, true, extra ); 6879 } 6880 6881 // Otherwise, if a way to get the computed value exists, use that 6882 if ( val === undefined ) { 6883 val = curCSS( elem, name, styles ); 6884 } 6885 6886 // Convert "normal" to computed value 6887 if ( val === "normal" && name in cssNormalTransform ) { 6888 val = cssNormalTransform[ name ]; 6889 } 6890 6891 // Make numeric if forced or a qualifier was provided and val looks numeric 6892 if ( extra === "" || extra ) { 6893 num = parseFloat( val ); 6894 return extra === true || isFinite( num ) ? num || 0 : val; 6895 } 6896 6897 return val; 6898 } 6899} ); 6900 6901jQuery.each( [ "height", "width" ], function( _i, dimension ) { 6902 jQuery.cssHooks[ dimension ] = { 6903 get: function( elem, computed, extra ) { 6904 if ( computed ) { 6905 6906 // Certain elements can have dimension info if we invisibly show them 6907 // but it must have a current display style that would benefit 6908 return rdisplayswap.test( jQuery.css( elem, "display" ) ) && 6909 6910 // Support: Safari 8+ 6911 // Table columns in Safari have non-zero offsetWidth & zero 6912 // getBoundingClientRect().width unless display is changed. 6913 // Support: IE <=11 only 6914 // Running getBoundingClientRect on a disconnected node 6915 // in IE throws an error. 6916 ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? 6917 swap( elem, cssShow, function() { 6918 return getWidthOrHeight( elem, dimension, extra ); 6919 } ) : 6920 getWidthOrHeight( elem, dimension, extra ); 6921 } 6922 }, 6923 6924 set: function( elem, value, extra ) { 6925 var matches, 6926 styles = getStyles( elem ), 6927 6928 // Only read styles.position if the test has a chance to fail 6929 // to avoid forcing a reflow. 6930 scrollboxSizeBuggy = !support.scrollboxSize() && 6931 styles.position === "absolute", 6932 6933 // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) 6934 boxSizingNeeded = scrollboxSizeBuggy || extra, 6935 isBorderBox = boxSizingNeeded && 6936 jQuery.css( elem, "boxSizing", false, styles ) === "border-box", 6937 subtract = extra ? 6938 boxModelAdjustment( 6939 elem, 6940 dimension, 6941 extra, 6942 isBorderBox, 6943 styles 6944 ) : 6945 0; 6946 6947 // Account for unreliable border-box dimensions by comparing offset* to computed and 6948 // faking a content-box to get border and padding (gh-3699) 6949 if ( isBorderBox && scrollboxSizeBuggy ) { 6950 subtract -= Math.ceil( 6951 elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - 6952 parseFloat( styles[ dimension ] ) - 6953 boxModelAdjustment( elem, dimension, "border", false, styles ) - 6954 0.5 6955 ); 6956 } 6957 6958 // Convert to pixels if value adjustment is needed 6959 if ( subtract && ( matches = rcssNum.exec( value ) ) && 6960 ( matches[ 3 ] || "px" ) !== "px" ) { 6961 6962 elem.style[ dimension ] = value; 6963 value = jQuery.css( elem, dimension ); 6964 } 6965 6966 return setPositiveNumber( elem, value, subtract ); 6967 } 6968 }; 6969} ); 6970 6971jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, 6972 function( elem, computed ) { 6973 if ( computed ) { 6974 return ( parseFloat( curCSS( elem, "marginLeft" ) ) || 6975 elem.getBoundingClientRect().left - 6976 swap( elem, { marginLeft: 0 }, function() { 6977 return elem.getBoundingClientRect().left; 6978 } ) 6979 ) + "px"; 6980 } 6981 } 6982); 6983 6984// These hooks are used by animate to expand properties 6985jQuery.each( { 6986 margin: "", 6987 padding: "", 6988 border: "Width" 6989}, function( prefix, suffix ) { 6990 jQuery.cssHooks[ prefix + suffix ] = { 6991 expand: function( value ) { 6992 var i = 0, 6993 expanded = {}, 6994 6995 // Assumes a single number if not a string 6996 parts = typeof value === "string" ? value.split( " " ) : [ value ]; 6997 6998 for ( ; i < 4; i++ ) { 6999 expanded[ prefix + cssExpand[ i ] + suffix ] = 7000 parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; 7001 } 7002 7003 return expanded; 7004 } 7005 }; 7006 7007 if ( prefix !== "margin" ) { 7008 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; 7009 } 7010} ); 7011 7012jQuery.fn.extend( { 7013 css: function( name, value ) { 7014 return access( this, function( elem, name, value ) { 7015 var styles, len, 7016 map = {}, 7017 i = 0; 7018 7019 if ( Array.isArray( name ) ) { 7020 styles = getStyles( elem ); 7021 len = name.length; 7022 7023 for ( ; i < len; i++ ) { 7024 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); 7025 } 7026 7027 return map; 7028 } 7029 7030 return value !== undefined ? 7031 jQuery.style( elem, name, value ) : 7032 jQuery.css( elem, name ); 7033 }, name, value, arguments.length > 1 ); 7034 } 7035} ); 7036 7037 7038function Tween( elem, options, prop, end, easing ) { 7039 return new Tween.prototype.init( elem, options, prop, end, easing ); 7040} 7041jQuery.Tween = Tween; 7042 7043Tween.prototype = { 7044 constructor: Tween, 7045 init: function( elem, options, prop, end, easing, unit ) { 7046 this.elem = elem; 7047 this.prop = prop; 7048 this.easing = easing || jQuery.easing._default; 7049 this.options = options; 7050 this.start = this.now = this.cur(); 7051 this.end = end; 7052 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); 7053 }, 7054 cur: function() { 7055 var hooks = Tween.propHooks[ this.prop ]; 7056 7057 return hooks && hooks.get ? 7058 hooks.get( this ) : 7059 Tween.propHooks._default.get( this ); 7060 }, 7061 run: function( percent ) { 7062 var eased, 7063 hooks = Tween.propHooks[ this.prop ]; 7064 7065 if ( this.options.duration ) { 7066 this.pos = eased = jQuery.easing[ this.easing ]( 7067 percent, this.options.duration * percent, 0, 1, this.options.duration 7068 ); 7069 } else { 7070 this.pos = eased = percent; 7071 } 7072 this.now = ( this.end - this.start ) * eased + this.start; 7073 7074 if ( this.options.step ) { 7075 this.options.step.call( this.elem, this.now, this ); 7076 } 7077 7078 if ( hooks && hooks.set ) { 7079 hooks.set( this ); 7080 } else { 7081 Tween.propHooks._default.set( this ); 7082 } 7083 return this; 7084 } 7085}; 7086 7087Tween.prototype.init.prototype = Tween.prototype; 7088 7089Tween.propHooks = { 7090 _default: { 7091 get: function( tween ) { 7092 var result; 7093 7094 // Use a property on the element directly when it is not a DOM element, 7095 // or when there is no matching style property that exists. 7096 if ( tween.elem.nodeType !== 1 || 7097 tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { 7098 return tween.elem[ tween.prop ]; 7099 } 7100 7101 // Passing an empty string as a 3rd parameter to .css will automatically 7102 // attempt a parseFloat and fallback to a string if the parse fails. 7103 // Simple values such as "10px" are parsed to Float; 7104 // complex values such as "rotate(1rad)" are returned as-is. 7105 result = jQuery.css( tween.elem, tween.prop, "" ); 7106 7107 // Empty strings, null, undefined and "auto" are converted to 0. 7108 return !result || result === "auto" ? 0 : result; 7109 }, 7110 set: function( tween ) { 7111 7112 // Use step hook for back compat. 7113 // Use cssHook if its there. 7114 // Use .style if available and use plain properties where available. 7115 if ( jQuery.fx.step[ tween.prop ] ) { 7116 jQuery.fx.step[ tween.prop ]( tween ); 7117 } else if ( tween.elem.nodeType === 1 && ( 7118 jQuery.cssHooks[ tween.prop ] || 7119 tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { 7120 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); 7121 } else { 7122 tween.elem[ tween.prop ] = tween.now; 7123 } 7124 } 7125 } 7126}; 7127 7128// Support: IE <=9 only 7129// Panic based approach to setting things on disconnected nodes 7130Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { 7131 set: function( tween ) { 7132 if ( tween.elem.nodeType && tween.elem.parentNode ) { 7133 tween.elem[ tween.prop ] = tween.now; 7134 } 7135 } 7136}; 7137 7138jQuery.easing = { 7139 linear: function( p ) { 7140 return p; 7141 }, 7142 swing: function( p ) { 7143 return 0.5 - Math.cos( p * Math.PI ) / 2; 7144 }, 7145 _default: "swing" 7146}; 7147 7148jQuery.fx = Tween.prototype.init; 7149 7150// Back compat <1.8 extension point 7151jQuery.fx.step = {}; 7152 7153 7154 7155 7156var 7157 fxNow, inProgress, 7158 rfxtypes = /^(?:toggle|show|hide)$/, 7159 rrun = /queueHooks$/; 7160 7161function schedule() { 7162 if ( inProgress ) { 7163 if ( document.hidden === false && window.requestAnimationFrame ) { 7164 window.requestAnimationFrame( schedule ); 7165 } else { 7166 window.setTimeout( schedule, jQuery.fx.interval ); 7167 } 7168 7169 jQuery.fx.tick(); 7170 } 7171} 7172 7173// Animations created synchronously will run synchronously 7174function createFxNow() { 7175 window.setTimeout( function() { 7176 fxNow = undefined; 7177 } ); 7178 return ( fxNow = Date.now() ); 7179} 7180 7181// Generate parameters to create a standard animation 7182function genFx( type, includeWidth ) { 7183 var which, 7184 i = 0, 7185 attrs = { height: type }; 7186 7187 // If we include width, step value is 1 to do all cssExpand values, 7188 // otherwise step value is 2 to skip over Left and Right 7189 includeWidth = includeWidth ? 1 : 0; 7190 for ( ; i < 4; i += 2 - includeWidth ) { 7191 which = cssExpand[ i ]; 7192 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; 7193 } 7194 7195 if ( includeWidth ) { 7196 attrs.opacity = attrs.width = type; 7197 } 7198 7199 return attrs; 7200} 7201 7202function createTween( value, prop, animation ) { 7203 var tween, 7204 collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), 7205 index = 0, 7206 length = collection.length; 7207 for ( ; index < length; index++ ) { 7208 if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { 7209 7210 // We're done with this property 7211 return tween; 7212 } 7213 } 7214} 7215 7216function defaultPrefilter( elem, props, opts ) { 7217 var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, 7218 isBox = "width" in props || "height" in props, 7219 anim = this, 7220 orig = {}, 7221 style = elem.style, 7222 hidden = elem.nodeType && isHiddenWithinTree( elem ), 7223 dataShow = dataPriv.get( elem, "fxshow" ); 7224 7225 // Queue-skipping animations hijack the fx hooks 7226 if ( !opts.queue ) { 7227 hooks = jQuery._queueHooks( elem, "fx" ); 7228 if ( hooks.unqueued == null ) { 7229 hooks.unqueued = 0; 7230 oldfire = hooks.empty.fire; 7231 hooks.empty.fire = function() { 7232 if ( !hooks.unqueued ) { 7233 oldfire(); 7234 } 7235 }; 7236 } 7237 hooks.unqueued++; 7238 7239 anim.always( function() { 7240 7241 // Ensure the complete handler is called before this completes 7242 anim.always( function() { 7243 hooks.unqueued--; 7244 if ( !jQuery.queue( elem, "fx" ).length ) { 7245 hooks.empty.fire(); 7246 } 7247 } ); 7248 } ); 7249 } 7250 7251 // Detect show/hide animations 7252 for ( prop in props ) { 7253 value = props[ prop ]; 7254 if ( rfxtypes.test( value ) ) { 7255 delete props[ prop ]; 7256 toggle = toggle || value === "toggle"; 7257 if ( value === ( hidden ? "hide" : "show" ) ) { 7258 7259 // Pretend to be hidden if this is a "show" and 7260 // there is still data from a stopped show/hide 7261 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { 7262 hidden = true; 7263 7264 // Ignore all other no-op show/hide data 7265 } else { 7266 continue; 7267 } 7268 } 7269 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); 7270 } 7271 } 7272 7273 // Bail out if this is a no-op like .hide().hide() 7274 propTween = !jQuery.isEmptyObject( props ); 7275 if ( !propTween && jQuery.isEmptyObject( orig ) ) { 7276 return; 7277 } 7278 7279 // Restrict "overflow" and "display" styles during box animations 7280 if ( isBox && elem.nodeType === 1 ) { 7281
vendor: 4,381 bytes, lines 7282-7441
7282 // Support: IE <=9 - 11, Edge 12 - 15 7283 // Record all 3 overflow attributes because IE does not infer the shorthand 7284 // from identically-valued overflowX and overflowY and Edge just mirrors 7285 // the overflowX value there. 7286 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; 7287 7288 // Identify a display type, preferring old show/hide data over the CSS cascade 7289 restoreDisplay = dataShow && dataShow.display; 7290 if ( restoreDisplay == null ) { 7291 restoreDisplay = dataPriv.get( elem, "display" ); 7292 } 7293 display = jQuery.css( elem, "display" ); 7294 if ( display === "none" ) { 7295 if ( restoreDisplay ) { 7296 display = restoreDisplay; 7297 } else { 7298 7299 // Get nonempty value(s) by temporarily forcing visibility 7300 showHide( [ elem ], true ); 7301 restoreDisplay = elem.style.display || restoreDisplay; 7302 display = jQuery.css( elem, "display" ); 7303 showHide( [ elem ] ); 7304 } 7305 } 7306 7307 // Animate inline elements as inline-block 7308 if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { 7309 if ( jQuery.css( elem, "float" ) === "none" ) { 7310 7311 // Restore the original display value at the end of pure show/hide animations 7312 if ( !propTween ) { 7313 anim.done( function() { 7314 style.display = restoreDisplay; 7315 } ); 7316 if ( restoreDisplay == null ) { 7317 display = style.display; 7318 restoreDisplay = display === "none" ? "" : display; 7319 } 7320 } 7321 style.display = "inline-block"; 7322 } 7323 } 7324 } 7325 7326 if ( opts.overflow ) { 7327 style.overflow = "hidden"; 7328 anim.always( function() { 7329 style.overflow = opts.overflow[ 0 ]; 7330 style.overflowX = opts.overflow[ 1 ]; 7331 style.overflowY = opts.overflow[ 2 ]; 7332 } ); 7333 } 7334 7335 // Implement show/hide animations 7336 propTween = false; 7337 for ( prop in orig ) { 7338 7339 // General show/hide setup for this element animation 7340 if ( !propTween ) { 7341 if ( dataShow ) { 7342 if ( "hidden" in dataShow ) { 7343 hidden = dataShow.hidden; 7344 } 7345 } else { 7346 dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); 7347 } 7348 7349 // Store hidden/visible for toggle so `.stop().toggle()` "reverses" 7350 if ( toggle ) { 7351 dataShow.hidden = !hidden; 7352 } 7353 7354 // Show elements before animating them 7355 if ( hidden ) { 7356 showHide( [ elem ], true ); 7357 } 7358 7359 /* eslint-disable no-loop-func */ 7360 7361 anim.done( function() { 7362 7363 /* eslint-enable no-loop-func */ 7364 7365 // The final step of a "hide" animation is actually hiding the element 7366 if ( !hidden ) { 7367 showHide( [ elem ] ); 7368 } 7369 dataPriv.remove( elem, "fxshow" ); 7370 for ( prop in orig ) { 7371 jQuery.style( elem, prop, orig[ prop ] ); 7372 } 7373 } ); 7374 } 7375 7376 // Per-property setup 7377 propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); 7378 if ( !( prop in dataShow ) ) { 7379 dataShow[ prop ] = propTween.start; 7380 if ( hidden ) { 7381 propTween.end = propTween.start; 7382 propTween.start = 0; 7383 } 7384 } 7385 } 7386} 7387 7388function propFilter( props, specialEasing ) { 7389 var index, name, easing, value, hooks; 7390 7391 // camelCase, specialEasing and expand cssHook pass 7392 for ( index in props ) { 7393 name = camelCase( index ); 7394 easing = specialEasing[ name ]; 7395 value = props[ index ]; 7396 if ( Array.isArray( value ) ) { 7397 easing = value[ 1 ]; 7398 value = props[ index ] = value[ 0 ]; 7399 } 7400 7401 if ( index !== name ) { 7402 props[ name ] = value; 7403 delete props[ index ]; 7404 } 7405 7406 hooks = jQuery.cssHooks[ name ]; 7407 if ( hooks && "expand" in hooks ) { 7408 value = hooks.expand( value ); 7409 delete props[ name ]; 7410 7411 // Not quite $.extend, this won't overwrite existing keys. 7412 // Reusing 'index' because we have the correct "name" 7413 for ( index in value ) { 7414 if ( !( index in props ) ) { 7415 props[ index ] = value[ index ]; 7416 specialEasing[ index ] = easing; 7417 } 7418 } 7419 } else { 7420 specialEasing[ name ] = easing; 7421 } 7422 } 7423} 7424 7425function Animation( elem, properties, options ) { 7426 var result, 7427 stopped, 7428 index = 0, 7429 length = Animation.prefilters.length, 7430 deferred = jQuery.Deferred().always( function() { 7431 7432 // Don't match elem in the :animated selector 7433 delete tick.elem; 7434 } ), 7435 tick = function() { 7436 if ( stopped ) { 7437 return false; 7438 } 7439 var currentTime = fxNow || createFxNow(), 7440 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), 7441
vendor: 39,713 bytes, lines 7442-8992
7442 // Support: Android 2.3 only 7443 // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (trac-12497) 7444 temp = remaining / animation.duration || 0, 7445 percent = 1 - temp, 7446 index = 0, 7447 length = animation.tweens.length; 7448 7449 for ( ; index < length; index++ ) { 7450 animation.tweens[ index ].run( percent ); 7451 } 7452 7453 deferred.notifyWith( elem, [ animation, percent, remaining ] ); 7454 7455 // If there's more to do, yield 7456 if ( percent < 1 && length ) { 7457 return remaining; 7458 } 7459 7460 // If this was an empty animation, synthesize a final progress notification 7461 if ( !length ) { 7462 deferred.notifyWith( elem, [ animation, 1, 0 ] ); 7463 } 7464 7465 // Resolve the animation and report its conclusion 7466 deferred.resolveWith( elem, [ animation ] ); 7467 return false; 7468 }, 7469 animation = deferred.promise( { 7470 elem: elem, 7471 props: jQuery.extend( {}, properties ), 7472 opts: jQuery.extend( true, { 7473 specialEasing: {}, 7474 easing: jQuery.easing._default 7475 }, options ), 7476 originalProperties: properties, 7477 originalOptions: options, 7478 startTime: fxNow || createFxNow(), 7479 duration: options.duration, 7480 tweens: [], 7481 createTween: function( prop, end ) { 7482 var tween = jQuery.Tween( elem, animation.opts, prop, end, 7483 animation.opts.specialEasing[ prop ] || animation.opts.easing ); 7484 animation.tweens.push( tween ); 7485 return tween; 7486 }, 7487 stop: function( gotoEnd ) { 7488 var index = 0, 7489 7490 // If we are going to the end, we want to run all the tweens 7491 // otherwise we skip this part 7492 length = gotoEnd ? animation.tweens.length : 0; 7493 if ( stopped ) { 7494 return this; 7495 } 7496 stopped = true; 7497 for ( ; index < length; index++ ) { 7498 animation.tweens[ index ].run( 1 ); 7499 } 7500 7501 // Resolve when we played the last frame; otherwise, reject 7502 if ( gotoEnd ) { 7503 deferred.notifyWith( elem, [ animation, 1, 0 ] ); 7504 deferred.resolveWith( elem, [ animation, gotoEnd ] ); 7505 } else { 7506 deferred.rejectWith( elem, [ animation, gotoEnd ] ); 7507 } 7508 return this; 7509 } 7510 } ), 7511 props = animation.props; 7512 7513 propFilter( props, animation.opts.specialEasing ); 7514 7515 for ( ; index < length; index++ ) { 7516 result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); 7517 if ( result ) { 7518 if ( isFunction( result.stop ) ) { 7519 jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = 7520 result.stop.bind( result ); 7521 } 7522 return result; 7523 } 7524 } 7525 7526 jQuery.map( props, createTween, animation ); 7527 7528 if ( isFunction( animation.opts.start ) ) { 7529 animation.opts.start.call( elem, animation ); 7530 } 7531 7532 // Attach callbacks from options 7533 animation 7534 .progress( animation.opts.progress ) 7535 .done( animation.opts.done, animation.opts.complete ) 7536 .fail( animation.opts.fail ) 7537 .always( animation.opts.always ); 7538 7539 jQuery.fx.timer( 7540 jQuery.extend( tick, { 7541 elem: elem, 7542 anim: animation, 7543 queue: animation.opts.queue 7544 } ) 7545 ); 7546 7547 return animation; 7548} 7549 7550jQuery.Animation = jQuery.extend( Animation, { 7551 7552 tweeners: { 7553 "*": [ function( prop, value ) { 7554 var tween = this.createTween( prop, value ); 7555 adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); 7556 return tween; 7557 } ] 7558 }, 7559 7560 tweener: function( props, callback ) { 7561 if ( isFunction( props ) ) { 7562 callback = props; 7563 props = [ "*" ]; 7564 } else { 7565 props = props.match( rnothtmlwhite ); 7566 } 7567 7568 var prop, 7569 index = 0, 7570 length = props.length; 7571 7572 for ( ; index < length; index++ ) { 7573 prop = props[ index ]; 7574 Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; 7575 Animation.tweeners[ prop ].unshift( callback ); 7576 } 7577 }, 7578 7579 prefilters: [ defaultPrefilter ], 7580 7581 prefilter: function( callback, prepend ) { 7582 if ( prepend ) { 7583 Animation.prefilters.unshift( callback ); 7584 } else { 7585 Animation.prefilters.push( callback ); 7586 } 7587 } 7588} ); 7589 7590jQuery.speed = function( speed, easing, fn ) { 7591 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { 7592 complete: fn || !fn && easing || 7593 isFunction( speed ) && speed, 7594 duration: speed, 7595 easing: fn && easing || easing && !isFunction( easing ) && easing 7596 }; 7597 7598 // Go to the end state if fx are off 7599 if ( jQuery.fx.off ) { 7600 opt.duration = 0; 7601 7602 } else { 7603 if ( typeof opt.duration !== "number" ) { 7604 if ( opt.duration in jQuery.fx.speeds ) { 7605 opt.duration = jQuery.fx.speeds[ opt.duration ]; 7606 7607 } else { 7608 opt.duration = jQuery.fx.speeds._default; 7609 } 7610 } 7611 } 7612 7613 // Normalize opt.queue - true/undefined/null -> "fx" 7614 if ( opt.queue == null || opt.queue === true ) { 7615 opt.queue = "fx"; 7616 } 7617 7618 // Queueing 7619 opt.old = opt.complete; 7620 7621 opt.complete = function() { 7622 if ( isFunction( opt.old ) ) { 7623 opt.old.call( this ); 7624 } 7625 7626 if ( opt.queue ) { 7627 jQuery.dequeue( this, opt.queue ); 7628 } 7629 }; 7630 7631 return opt; 7632}; 7633 7634jQuery.fn.extend( { 7635 fadeTo: function( speed, to, easing, callback ) { 7636 7637 // Show any hidden elements after setting opacity to 0 7638 return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() 7639 7640 // Animate to the value specified 7641 .end().animate( { opacity: to }, speed, easing, callback ); 7642 }, 7643 animate: function( prop, speed, easing, callback ) { 7644 var empty = jQuery.isEmptyObject( prop ), 7645 optall = jQuery.speed( speed, easing, callback ), 7646 doAnimation = function() { 7647 7648 // Operate on a copy of prop so per-property easing won't be lost 7649 var anim = Animation( this, jQuery.extend( {}, prop ), optall ); 7650 7651 // Empty animations, or finishing resolves immediately 7652 if ( empty || dataPriv.get( this, "finish" ) ) { 7653 anim.stop( true ); 7654 } 7655 }; 7656 7657 doAnimation.finish = doAnimation; 7658 7659 return empty || optall.queue === false ? 7660 this.each( doAnimation ) : 7661 this.queue( optall.queue, doAnimation ); 7662 }, 7663 stop: function( type, clearQueue, gotoEnd ) { 7664 var stopQueue = function( hooks ) { 7665 var stop = hooks.stop; 7666 delete hooks.stop; 7667 stop( gotoEnd ); 7668 }; 7669 7670 if ( typeof type !== "string" ) { 7671 gotoEnd = clearQueue; 7672 clearQueue = type; 7673 type = undefined; 7674 } 7675 if ( clearQueue ) { 7676 this.queue( type || "fx", [] ); 7677 } 7678 7679 return this.each( function() { 7680 var dequeue = true, 7681 index = type != null && type + "queueHooks", 7682 timers = jQuery.timers, 7683 data = dataPriv.get( this ); 7684 7685 if ( index ) { 7686 if ( data[ index ] && data[ index ].stop ) { 7687 stopQueue( data[ index ] ); 7688 } 7689 } else { 7690 for ( index in data ) { 7691 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { 7692 stopQueue( data[ index ] ); 7693 } 7694 } 7695 } 7696 7697 for ( index = timers.length; index--; ) { 7698 if ( timers[ index ].elem === this && 7699 ( type == null || timers[ index ].queue === type ) ) { 7700 7701 timers[ index ].anim.stop( gotoEnd ); 7702 dequeue = false; 7703 timers.splice( index, 1 ); 7704 } 7705 } 7706 7707 // Start the next in the queue if the last step wasn't forced. 7708 // Timers currently will call their complete callbacks, which 7709 // will dequeue but only if they were gotoEnd. 7710 if ( dequeue || !gotoEnd ) { 7711 jQuery.dequeue( this, type ); 7712 } 7713 } ); 7714 }, 7715 finish: function( type ) { 7716 if ( type !== false ) { 7717 type = type || "fx"; 7718 } 7719 return this.each( function() { 7720 var index, 7721 data = dataPriv.get( this ), 7722 queue = data[ type + "queue" ], 7723 hooks = data[ type + "queueHooks" ], 7724 timers = jQuery.timers, 7725 length = queue ? queue.length : 0; 7726 7727 // Enable finishing flag on private data 7728 data.finish = true; 7729 7730 // Empty the queue first 7731 jQuery.queue( this, type, [] ); 7732 7733 if ( hooks && hooks.stop ) { 7734 hooks.stop.call( this, true ); 7735 } 7736 7737 // Look for any active animations, and finish them 7738 for ( index = timers.length; index--; ) { 7739 if ( timers[ index ].elem === this && timers[ index ].queue === type ) { 7740 timers[ index ].anim.stop( true ); 7741 timers.splice( index, 1 ); 7742 } 7743 } 7744 7745 // Look for any animations in the old queue and finish them 7746 for ( index = 0; index < length; index++ ) { 7747 if ( queue[ index ] && queue[ index ].finish ) { 7748 queue[ index ].finish.call( this ); 7749 } 7750 } 7751 7752 // Turn off finishing flag 7753 delete data.finish; 7754 } ); 7755 } 7756} ); 7757 7758jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { 7759 var cssFn = jQuery.fn[ name ]; 7760 jQuery.fn[ name ] = function( speed, easing, callback ) { 7761 return speed == null || typeof speed === "boolean" ? 7762 cssFn.apply( this, arguments ) : 7763 this.animate( genFx( name, true ), speed, easing, callback ); 7764 }; 7765} ); 7766 7767// Generate shortcuts for custom animations 7768jQuery.each( { 7769 slideDown: genFx( "show" ), 7770 slideUp: genFx( "hide" ), 7771 slideToggle: genFx( "toggle" ), 7772 fadeIn: { opacity: "show" }, 7773 fadeOut: { opacity: "hide" }, 7774 fadeToggle: { opacity: "toggle" } 7775}, function( name, props ) { 7776 jQuery.fn[ name ] = function( speed, easing, callback ) { 7777 return this.animate( props, speed, easing, callback ); 7778 }; 7779} ); 7780 7781jQuery.timers = []; 7782jQuery.fx.tick = function() { 7783 var timer, 7784 i = 0, 7785 timers = jQuery.timers; 7786 7787 fxNow = Date.now(); 7788 7789 for ( ; i < timers.length; i++ ) { 7790 timer = timers[ i ]; 7791 7792 // Run the timer and safely remove it when done (allowing for external removal) 7793 if ( !timer() && timers[ i ] === timer ) { 7794 timers.splice( i--, 1 ); 7795 } 7796 } 7797 7798 if ( !timers.length ) { 7799 jQuery.fx.stop(); 7800 } 7801 fxNow = undefined; 7802}; 7803 7804jQuery.fx.timer = function( timer ) { 7805 jQuery.timers.push( timer ); 7806 jQuery.fx.start(); 7807}; 7808 7809jQuery.fx.interval = 13; 7810jQuery.fx.start = function() { 7811 if ( inProgress ) { 7812 return; 7813 } 7814 7815 inProgress = true; 7816 schedule(); 7817}; 7818 7819jQuery.fx.stop = function() { 7820 inProgress = null; 7821}; 7822 7823jQuery.fx.speeds = { 7824 slow: 600, 7825 fast: 200, 7826 7827 // Default speed 7828 _default: 400 7829}; 7830 7831 7832// Based off of the plugin by Clint Helfers, with permission. 7833jQuery.fn.delay = function( time, type ) { 7834 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; 7835 type = type || "fx"; 7836 7837 return this.queue( type, function( next, hooks ) { 7838 var timeout = window.setTimeout( next, time ); 7839 hooks.stop = function() { 7840 window.clearTimeout( timeout ); 7841 }; 7842 } ); 7843}; 7844 7845 7846( function() { 7847 var input = document.createElement( "input" ), 7848 select = document.createElement( "select" ), 7849 opt = select.appendChild( document.createElement( "option" ) ); 7850 7851 input.type = "checkbox"; 7852 7853 // Support: Android <=4.3 only 7854 // Default value for a checkbox should be "on" 7855 support.checkOn = input.value !== ""; 7856 7857 // Support: IE <=11 only 7858 // Must access selectedIndex to make default options select 7859 support.optSelected = opt.selected; 7860 7861 // Support: IE <=11 only 7862 // An input loses its value after becoming a radio 7863 input = document.createElement( "input" ); 7864 input.value = "t"; 7865 input.type = "radio"; 7866 support.radioValue = input.value === "t"; 7867} )(); 7868 7869 7870var boolHook, 7871 attrHandle = jQuery.expr.attrHandle; 7872 7873jQuery.fn.extend( { 7874 attr: function( name, value ) { 7875 return access( this, jQuery.attr, name, value, arguments.length > 1 ); 7876 }, 7877 7878 removeAttr: function( name ) { 7879 return this.each( function() { 7880 jQuery.removeAttr( this, name ); 7881 } ); 7882 } 7883} ); 7884 7885jQuery.extend( { 7886 attr: function( elem, name, value ) { 7887 var ret, hooks, 7888 nType = elem.nodeType; 7889 7890 // Don't get/set attributes on text, comment and attribute nodes 7891 if ( nType === 3 || nType === 8 || nType === 2 ) { 7892 return; 7893 } 7894 7895 // Fallback to prop when attributes are not supported 7896 if ( typeof elem.getAttribute === "undefined" ) { 7897 return jQuery.prop( elem, name, value ); 7898 } 7899 7900 // Attribute hooks are determined by the lowercase version 7901 // Grab necessary hook if one is defined 7902 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { 7903 hooks = jQuery.attrHooks[ name.toLowerCase() ] || 7904 ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); 7905 } 7906 7907 if ( value !== undefined ) { 7908 if ( value === null ) { 7909 jQuery.removeAttr( elem, name ); 7910 return; 7911 } 7912 7913 if ( hooks && "set" in hooks && 7914 ( ret = hooks.set( elem, value, name ) ) !== undefined ) { 7915 return ret; 7916 } 7917 7918 elem.setAttribute( name, value + "" ); 7919 return value; 7920 } 7921 7922 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { 7923 return ret; 7924 } 7925 7926 ret = jQuery.find.attr( elem, name ); 7927 7928 // Non-existent attributes return null, we normalize to undefined 7929 return ret == null ? undefined : ret; 7930 }, 7931 7932 attrHooks: { 7933 type: { 7934 set: function( elem, value ) { 7935 if ( !support.radioValue && value === "radio" && 7936 nodeName( elem, "input" ) ) { 7937 var val = elem.value; 7938 elem.setAttribute( "type", value ); 7939 if ( val ) { 7940 elem.value = val; 7941 } 7942 return value; 7943 } 7944 } 7945 } 7946 }, 7947 7948 removeAttr: function( elem, value ) { 7949 var name, 7950 i = 0, 7951 7952 // Attribute names can contain non-HTML whitespace characters 7953 // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 7954 attrNames = value && value.match( rnothtmlwhite ); 7955 7956 if ( attrNames && elem.nodeType === 1 ) { 7957 while ( ( name = attrNames[ i++ ] ) ) { 7958 elem.removeAttribute( name ); 7959 } 7960 } 7961 } 7962} ); 7963 7964// Hooks for boolean attributes 7965boolHook = { 7966 set: function( elem, value, name ) { 7967 if ( value === false ) { 7968 7969 // Remove boolean attributes when set to false 7970 jQuery.removeAttr( elem, name ); 7971 } else { 7972 elem.setAttribute( name, name ); 7973 } 7974 return name; 7975 } 7976}; 7977 7978jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { 7979 var getter = attrHandle[ name ] || jQuery.find.attr; 7980 7981 attrHandle[ name ] = function( elem, name, isXML ) { 7982 var ret, handle, 7983 lowercaseName = name.toLowerCase(); 7984 7985 if ( !isXML ) { 7986 7987 // Avoid an infinite loop by temporarily removing this function from the getter 7988 handle = attrHandle[ lowercaseName ]; 7989 attrHandle[ lowercaseName ] = ret; 7990 ret = getter( elem, name, isXML ) != null ? 7991 lowercaseName : 7992 null; 7993 attrHandle[ lowercaseName ] = handle; 7994 } 7995 return ret; 7996 }; 7997} ); 7998 7999 8000 8001 8002var rfocusable = /^(?:input|select|textarea|button)$/i, 8003 rclickable = /^(?:a|area)$/i; 8004 8005jQuery.fn.extend( { 8006 prop: function( name, value ) { 8007 return access( this, jQuery.prop, name, value, arguments.length > 1 ); 8008 }, 8009 8010 removeProp: function( name ) { 8011 return this.each( function() { 8012 delete this[ jQuery.propFix[ name ] || name ]; 8013 } ); 8014 } 8015} ); 8016 8017jQuery.extend( { 8018 prop: function( elem, name, value ) { 8019 var ret, hooks, 8020 nType = elem.nodeType; 8021 8022 // Don't get/set properties on text, comment and attribute nodes 8023 if ( nType === 3 || nType === 8 || nType === 2 ) { 8024 return; 8025 } 8026 8027 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { 8028 8029 // Fix name and attach hooks 8030 name = jQuery.propFix[ name ] || name; 8031 hooks = jQuery.propHooks[ name ]; 8032 } 8033 8034 if ( value !== undefined ) { 8035 if ( hooks && "set" in hooks && 8036 ( ret = hooks.set( elem, value, name ) ) !== undefined ) { 8037 return ret; 8038 } 8039 8040 return ( elem[ name ] = value ); 8041 } 8042 8043 if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { 8044 return ret; 8045 } 8046 8047 return elem[ name ]; 8048 }, 8049 8050 propHooks: { 8051 tabIndex: { 8052 get: function( elem ) { 8053 8054 // Support: IE <=9 - 11 only 8055 // elem.tabIndex doesn't always return the 8056 // correct value when it hasn't been explicitly set 8057 // Use proper attribute retrieval (trac-12072) 8058 var tabindex = jQuery.find.attr( elem, "tabindex" ); 8059 8060 if ( tabindex ) { 8061 return parseInt( tabindex, 10 ); 8062 } 8063 8064 if ( 8065 rfocusable.test( elem.nodeName ) || 8066 rclickable.test( elem.nodeName ) && 8067 elem.href 8068 ) { 8069 return 0; 8070 } 8071 8072 return -1; 8073 } 8074 } 8075 }, 8076 8077 propFix: { 8078 "for": "htmlFor", 8079 "class": "className" 8080 } 8081} ); 8082 8083// Support: IE <=11 only 8084// Accessing the selectedIndex property 8085// forces the browser to respect setting selected 8086// on the option 8087// The getter ensures a default option is selected 8088// when in an optgroup 8089// eslint rule "no-unused-expressions" is disabled for this code 8090// since it considers such accessions noop 8091if ( !support.optSelected ) { 8092 jQuery.propHooks.selected = { 8093 get: function( elem ) { 8094 8095 /* eslint no-unused-expressions: "off" */ 8096 8097 var parent = elem.parentNode; 8098 if ( parent && parent.parentNode ) { 8099 parent.parentNode.selectedIndex; 8100 } 8101 return null; 8102 }, 8103 set: function( elem ) { 8104 8105 /* eslint no-unused-expressions: "off" */ 8106 8107 var parent = elem.parentNode; 8108 if ( parent ) { 8109 parent.selectedIndex; 8110 8111 if ( parent.parentNode ) { 8112 parent.parentNode.selectedIndex; 8113 } 8114 } 8115 } 8116 }; 8117} 8118 8119jQuery.each( [ 8120 "tabIndex", 8121 "readOnly", 8122 "maxLength", 8123 "cellSpacing", 8124 "cellPadding", 8125 "rowSpan", 8126 "colSpan", 8127 "useMap", 8128 "frameBorder", 8129 "contentEditable" 8130], function() { 8131 jQuery.propFix[ this.toLowerCase() ] = this; 8132} ); 8133 8134 8135 8136 8137 // Strip and collapse whitespace according to HTML spec 8138 // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace 8139 function stripAndCollapse( value ) { 8140 var tokens = value.match( rnothtmlwhite ) || []; 8141 return tokens.join( " " ); 8142 } 8143 8144 8145function getClass( elem ) { 8146 return elem.getAttribute && elem.getAttribute( "class" ) || ""; 8147} 8148 8149function classesToArray( value ) { 8150 if ( Array.isArray( value ) ) { 8151 return value; 8152 } 8153 if ( typeof value === "string" ) { 8154 return value.match( rnothtmlwhite ) || []; 8155 } 8156 return []; 8157} 8158 8159jQuery.fn.extend( { 8160 addClass: function( value ) { 8161 var classNames, cur, curValue, className, i, finalValue; 8162 8163 if ( isFunction( value ) ) { 8164 return this.each( function( j ) { 8165 jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); 8166 } ); 8167 } 8168 8169 classNames = classesToArray( value ); 8170 8171 if ( classNames.length ) { 8172 return this.each( function() { 8173 curValue = getClass( this ); 8174 cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); 8175 8176 if ( cur ) { 8177 for ( i = 0; i < classNames.length; i++ ) { 8178 className = classNames[ i ]; 8179 if ( cur.indexOf( " " + className + " " ) < 0 ) { 8180 cur += className + " "; 8181 } 8182 } 8183 8184 // Only assign if different to avoid unneeded rendering. 8185 finalValue = stripAndCollapse( cur ); 8186 if ( curValue !== finalValue ) { 8187 this.setAttribute( "class", finalValue ); 8188 } 8189 } 8190 } ); 8191 } 8192 8193 return this; 8194 }, 8195 8196 removeClass: function( value ) { 8197 var classNames, cur, curValue, className, i, finalValue; 8198 8199 if ( isFunction( value ) ) { 8200 return this.each( function( j ) { 8201 jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); 8202 } ); 8203 } 8204 8205 if ( !arguments.length ) { 8206 return this.attr( "class", "" ); 8207 } 8208 8209 classNames = classesToArray( value ); 8210 8211 if ( classNames.length ) { 8212 return this.each( function() { 8213 curValue = getClass( this ); 8214 8215 // This expression is here for better compressibility (see addClass) 8216 cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); 8217 8218 if ( cur ) { 8219 for ( i = 0; i < classNames.length; i++ ) { 8220 className = classNames[ i ]; 8221 8222 // Remove *all* instances 8223 while ( cur.indexOf( " " + className + " " ) > -1 ) { 8224 cur = cur.replace( " " + className + " ", " " ); 8225 } 8226 } 8227 8228 // Only assign if different to avoid unneeded rendering. 8229 finalValue = stripAndCollapse( cur ); 8230 if ( curValue !== finalValue ) { 8231 this.setAttribute( "class", finalValue ); 8232 } 8233 } 8234 } ); 8235 } 8236 8237 return this; 8238 }, 8239 8240 toggleClass: function( value, stateVal ) { 8241 var classNames, className, i, self, 8242 type = typeof value, 8243 isValidValue = type === "string" || Array.isArray( value ); 8244 8245 if ( isFunction( value ) ) { 8246 return this.each( function( i ) { 8247 jQuery( this ).toggleClass( 8248 value.call( this, i, getClass( this ), stateVal ), 8249 stateVal 8250 ); 8251 } ); 8252 } 8253 8254 if ( typeof stateVal === "boolean" && isValidValue ) { 8255 return stateVal ? this.addClass( value ) : this.removeClass( value ); 8256 } 8257 8258 classNames = classesToArray( value ); 8259 8260 return this.each( function() { 8261 if ( isValidValue ) { 8262 8263 // Toggle individual class names 8264 self = jQuery( this ); 8265 8266 for ( i = 0; i < classNames.length; i++ ) { 8267 className = classNames[ i ]; 8268 8269 // Check each className given, space separated list 8270 if ( self.hasClass( className ) ) { 8271 self.removeClass( className ); 8272 } else { 8273 self.addClass( className ); 8274 } 8275 } 8276 8277 // Toggle whole class name 8278 } else if ( value === undefined || type === "boolean" ) { 8279 className = getClass( this ); 8280 if ( className ) { 8281 8282 // Store className if set 8283 dataPriv.set( this, "__className__", className ); 8284 } 8285 8286 // If the element has a class name or if we're passed `false`, 8287 // then remove the whole classname (if there was one, the above saved it). 8288 // Otherwise bring back whatever was previously saved (if anything), 8289 // falling back to the empty string if nothing was stored. 8290 if ( this.setAttribute ) { 8291 this.setAttribute( "class", 8292 className || value === false ? 8293 "" : 8294 dataPriv.get( this, "__className__" ) || "" 8295 ); 8296 } 8297 } 8298 } ); 8299 }, 8300 8301 hasClass: function( selector ) { 8302 var className, elem, 8303 i = 0; 8304 8305 className = " " + selector + " "; 8306 while ( ( elem = this[ i++ ] ) ) { 8307 if ( elem.nodeType === 1 && 8308 ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { 8309 return true; 8310 } 8311 } 8312 8313 return false; 8314 } 8315} ); 8316 8317 8318 8319 8320var rreturn = /\r/g; 8321 8322jQuery.fn.extend( { 8323 val: function( value ) { 8324 var hooks, ret, valueIsFunction, 8325 elem = this[ 0 ]; 8326 8327 if ( !arguments.length ) { 8328 if ( elem ) { 8329 hooks = jQuery.valHooks[ elem.type ] || 8330 jQuery.valHooks[ elem.nodeName.toLowerCase() ]; 8331 8332 if ( hooks && 8333 "get" in hooks && 8334 ( ret = hooks.get( elem, "value" ) ) !== undefined 8335 ) { 8336 return ret; 8337 } 8338 8339 ret = elem.value; 8340 8341 // Handle most common string cases 8342 if ( typeof ret === "string" ) { 8343 return ret.replace( rreturn, "" ); 8344 } 8345 8346 // Handle cases where value is null/undef or number 8347 return ret == null ? "" : ret; 8348 } 8349 8350 return; 8351 } 8352 8353 valueIsFunction = isFunction( value ); 8354 8355 return this.each( function( i ) { 8356 var val; 8357 8358 if ( this.nodeType !== 1 ) { 8359 return; 8360 } 8361 8362 if ( valueIsFunction ) { 8363 val = value.call( this, i, jQuery( this ).val() ); 8364 } else { 8365 val = value; 8366 } 8367 8368 // Treat null/undefined as ""; convert numbers to string 8369 if ( val == null ) { 8370 val = ""; 8371 8372 } else if ( typeof val === "number" ) { 8373 val += ""; 8374 8375 } else if ( Array.isArray( val ) ) { 8376 val = jQuery.map( val, function( value ) { 8377 return value == null ? "" : value + ""; 8378 } ); 8379 } 8380 8381 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; 8382 8383 // If set returns undefined, fall back to normal setting 8384 if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { 8385 this.value = val; 8386 } 8387 } ); 8388 } 8389} ); 8390 8391jQuery.extend( { 8392 valHooks: { 8393 option: { 8394 get: function( elem ) { 8395 8396 var val = jQuery.find.attr( elem, "value" ); 8397 return val != null ? 8398 val : 8399 8400 // Support: IE <=10 - 11 only 8401 // option.text throws exceptions (trac-14686, trac-14858) 8402 // Strip and collapse whitespace 8403 // https://html.spec.whatwg.org/#strip-and-collapse-whitespace 8404 stripAndCollapse( jQuery.text( elem ) ); 8405 } 8406 }, 8407 select: { 8408 get: function( elem ) { 8409 var value, option, i, 8410 options = elem.options, 8411 index = elem.selectedIndex, 8412 one = elem.type === "select-one", 8413 values = one ? null : [], 8414 max = one ? index + 1 : options.length; 8415 8416 if ( index < 0 ) { 8417 i = max; 8418 8419 } else { 8420 i = one ? index : 0; 8421 } 8422 8423 // Loop through all the selected options 8424 for ( ; i < max; i++ ) { 8425 option = options[ i ]; 8426 8427 // Support: IE <=9 only 8428 // IE8-9 doesn't update selected after form reset (trac-2551) 8429 if ( ( option.selected || i === index ) && 8430 8431 // Don't return options that are disabled or in a disabled optgroup 8432 !option.disabled && 8433 ( !option.parentNode.disabled || 8434 !nodeName( option.parentNode, "optgroup" ) ) ) { 8435 8436 // Get the specific value for the option 8437 value = jQuery( option ).val(); 8438 8439 // We don't need an array for one selects 8440 if ( one ) { 8441 return value; 8442 } 8443 8444 // Multi-Selects return an array 8445 values.push( value ); 8446 } 8447 } 8448 8449 return values; 8450 }, 8451 8452 set: function( elem, value ) { 8453 var optionSet, option, 8454 options = elem.options, 8455 values = jQuery.makeArray( value ), 8456 i = options.length; 8457 8458 while ( i-- ) { 8459 option = options[ i ]; 8460 8461 /* eslint-disable no-cond-assign */ 8462 8463 if ( option.selected = 8464 jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 8465 ) { 8466 optionSet = true; 8467 } 8468 8469 /* eslint-enable no-cond-assign */ 8470 } 8471 8472 // Force browsers to behave consistently when non-matching value is set 8473 if ( !optionSet ) { 8474 elem.selectedIndex = -1; 8475 } 8476 return values; 8477 } 8478 } 8479 } 8480} ); 8481 8482// Radios and checkboxes getter/setter 8483jQuery.each( [ "radio", "checkbox" ], function() { 8484 jQuery.valHooks[ this ] = { 8485 set: function( elem, value ) { 8486 if ( Array.isArray( value ) ) { 8487 return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); 8488 } 8489 } 8490 }; 8491 if ( !support.checkOn ) { 8492 jQuery.valHooks[ this ].get = function( elem ) { 8493 return elem.getAttribute( "value" ) === null ? "on" : elem.value; 8494 }; 8495 } 8496} ); 8497 8498 8499 8500 8501// Return jQuery for attributes-only inclusion 8502var location = window.location; 8503 8504var nonce = { guid: Date.now() }; 8505 8506var rquery = ( /\?/ ); 8507 8508 8509 8510// Cross-browser xml parsing 8511jQuery.parseXML = function( data ) { 8512 var xml, parserErrorElem; 8513 if ( !data || typeof data !== "string" ) { 8514 return null; 8515 } 8516 8517 // Support: IE 9 - 11 only 8518 // IE throws on parseFromString with invalid input. 8519 try { 8520 xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); 8521 } catch ( e ) {} 8522 8523 parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; 8524 if ( !xml || parserErrorElem ) { 8525 jQuery.error( "Invalid XML: " + ( 8526 parserErrorElem ? 8527 jQuery.map( parserErrorElem.childNodes, function( el ) { 8528 return el.textContent; 8529 } ).join( "\n" ) : 8530 data 8531 ) ); 8532 } 8533 return xml; 8534}; 8535 8536 8537var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, 8538 stopPropagationCallback = function( e ) { 8539 e.stopPropagation(); 8540 }; 8541 8542jQuery.extend( jQuery.event, { 8543 8544 trigger: function( event, data, elem, onlyHandlers ) { 8545 8546 var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, 8547 eventPath = [ elem || document ], 8548 type = hasOwn.call( event, "type" ) ? event.type : event, 8549 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; 8550 8551 cur = lastElement = tmp = elem = elem || document; 8552 8553 // Don't do events on text and comment nodes 8554 if ( elem.nodeType === 3 || elem.nodeType === 8 ) { 8555 return; 8556 } 8557 8558 // focus/blur morphs to focusin/out; ensure we're not firing them right now 8559 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { 8560 return; 8561 } 8562 8563 if ( type.indexOf( "." ) > -1 ) { 8564 8565 // Namespaced trigger; create a regexp to match event type in handle() 8566 namespaces = type.split( "." ); 8567 type = namespaces.shift(); 8568 namespaces.sort(); 8569 } 8570 ontype = type.indexOf( ":" ) < 0 && "on" + type; 8571 8572 // Caller can pass in a jQuery.Event object, Object, or just an event type string 8573 event = event[ jQuery.expando ] ? 8574 event : 8575 new jQuery.Event( type, typeof event === "object" && event ); 8576 8577 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) 8578 event.isTrigger = onlyHandlers ? 2 : 3; 8579 event.namespace = namespaces.join( "." ); 8580 event.rnamespace = event.namespace ? 8581 new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : 8582 null; 8583 8584 // Clean up the event in case it is being reused 8585 event.result = undefined; 8586 if ( !event.target ) { 8587 event.target = elem; 8588 } 8589 8590 // Clone any incoming data and prepend the event, creating the handler arg list 8591 data = data == null ? 8592 [ event ] : 8593 jQuery.makeArray( data, [ event ] ); 8594 8595 // Allow special events to draw outside the lines 8596 special = jQuery.event.special[ type ] || {}; 8597 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { 8598 return; 8599 } 8600 8601 // Determine event propagation path in advance, per W3C events spec (trac-9951) 8602 // Bubble up to document, then to window; watch for a global ownerDocument var (trac-9724) 8603 if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { 8604 8605 bubbleType = special.delegateType || type; 8606 if ( !rfocusMorph.test( bubbleType + type ) ) { 8607 cur = cur.parentNode; 8608 } 8609 for ( ; cur; cur = cur.parentNode ) { 8610 eventPath.push( cur ); 8611 tmp = cur; 8612 } 8613 8614 // Only add window if we got to document (e.g., not plain obj or detached DOM) 8615 if ( tmp === ( elem.ownerDocument || document ) ) { 8616 eventPath.push( tmp.defaultView || tmp.parentWindow || window ); 8617 } 8618 } 8619 8620 // Fire handlers on the event path 8621 i = 0; 8622 while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { 8623 lastElement = cur; 8624 event.type = i > 1 ? 8625 bubbleType : 8626 special.bindType || type; 8627 8628 // jQuery handler 8629 handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && 8630 dataPriv.get( cur, "handle" ); 8631 if ( handle ) { 8632 handle.apply( cur, data ); 8633 } 8634 8635 // Native handler 8636 handle = ontype && cur[ ontype ]; 8637 if ( handle && handle.apply && acceptData( cur ) ) { 8638 event.result = handle.apply( cur, data ); 8639 if ( event.result === false ) { 8640 event.preventDefault(); 8641 } 8642 } 8643 } 8644 event.type = type; 8645 8646 // If nobody prevented the default action, do it now 8647 if ( !onlyHandlers && !event.isDefaultPrevented() ) { 8648 8649 if ( ( !special._default || 8650 special._default.apply( eventPath.pop(), data ) === false ) && 8651 acceptData( elem ) ) { 8652 8653 // Call a native DOM method on the target with the same name as the event. 8654 // Don't do default actions on window, that's where global variables be (trac-6170) 8655 if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { 8656 8657 // Don't re-trigger an onFOO event when we call its FOO() method 8658 tmp = elem[ ontype ]; 8659 8660 if ( tmp ) { 8661 elem[ ontype ] = null; 8662 } 8663 8664 // Prevent re-triggering of the same event, since we already bubbled it above 8665 jQuery.event.triggered = type; 8666 8667 if ( event.isPropagationStopped() ) { 8668 lastElement.addEventListener( type, stopPropagationCallback ); 8669 } 8670 8671 elem[ type ](); 8672 8673 if ( event.isPropagationStopped() ) { 8674 lastElement.removeEventListener( type, stopPropagationCallback ); 8675 } 8676 8677 jQuery.event.triggered = undefined; 8678 8679 if ( tmp ) { 8680 elem[ ontype ] = tmp; 8681 } 8682 } 8683 } 8684 } 8685 8686 return event.result; 8687 }, 8688 8689 // Piggyback on a donor event to simulate a different one 8690 // Used only for `focus(in | out)` events 8691 simulate: function( type, elem, event ) { 8692 var e = jQuery.extend( 8693 new jQuery.Event(), 8694 event, 8695 { 8696 type: type, 8697 isSimulated: true 8698 } 8699 ); 8700 8701 jQuery.event.trigger( e, null, elem ); 8702 } 8703 8704} ); 8705 8706jQuery.fn.extend( { 8707 8708 trigger: function( type, data ) { 8709 return this.each( function() { 8710 jQuery.event.trigger( type, data, this ); 8711 } ); 8712 }, 8713 triggerHandler: function( type, data ) { 8714 var elem = this[ 0 ]; 8715 if ( elem ) { 8716 return jQuery.event.trigger( type, data, elem, true ); 8717 } 8718 } 8719} ); 8720 8721 8722var 8723 rbracket = /\[\]$/, 8724 rCRLF = /\r?\n/g, 8725 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, 8726 rsubmittable = /^(?:input|select|textarea|keygen)/i; 8727 8728function buildParams( prefix, obj, traditional, add ) { 8729 var name; 8730 8731 if ( Array.isArray( obj ) ) { 8732 8733 // Serialize array item. 8734 jQuery.each( obj, function( i, v ) { 8735 if ( traditional || rbracket.test( prefix ) ) { 8736 8737 // Treat each array item as a scalar. 8738 add( prefix, v ); 8739 8740 } else { 8741 8742 // Item is non-scalar (array or object), encode its numeric index. 8743 buildParams( 8744 prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", 8745 v, 8746 traditional, 8747 add 8748 ); 8749 } 8750 } ); 8751 8752 } else if ( !traditional && toType( obj ) === "object" ) { 8753 8754 // Serialize object item. 8755 for ( name in obj ) { 8756 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); 8757 } 8758 8759 } else { 8760 8761 // Serialize scalar item. 8762 add( prefix, obj ); 8763 } 8764} 8765 8766// Serialize an array of form elements or a set of 8767// key/values into a query string 8768jQuery.param = function( a, traditional ) { 8769 var prefix, 8770 s = [], 8771 add = function( key, valueOrFunction ) { 8772 8773 // If value is a function, invoke it and use its return value 8774 var value = isFunction( valueOrFunction ) ? 8775 valueOrFunction() : 8776 valueOrFunction; 8777 8778 s[ s.length ] = encodeURIComponent( key ) + "=" + 8779 encodeURIComponent( value == null ? "" : value ); 8780 }; 8781 8782 if ( a == null ) { 8783 return ""; 8784 } 8785 8786 // If an array was passed in, assume that it is an array of form elements. 8787 if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { 8788 8789 // Serialize the form elements 8790 jQuery.each( a, function() { 8791 add( this.name, this.value ); 8792 } ); 8793 8794 } else { 8795 8796 // If traditional, encode the "old" way (the way 1.3.2 or older 8797 // did it), otherwise encode params recursively. 8798 for ( prefix in a ) { 8799 buildParams( prefix, a[ prefix ], traditional, add ); 8800 } 8801 } 8802 8803 // Return the resulting serialization 8804 return s.join( "&" ); 8805}; 8806 8807jQuery.fn.extend( { 8808 serialize: function() { 8809 return jQuery.param( this.serializeArray() ); 8810 }, 8811 serializeArray: function() { 8812 return this.map( function() { 8813 8814 // Can add propHook for "elements" to filter or add form elements 8815 var elements = jQuery.prop( this, "elements" ); 8816 return elements ? jQuery.makeArray( elements ) : this; 8817 } ).filter( function() { 8818 var type = this.type; 8819 8820 // Use .is( ":disabled" ) so that fieldset[disabled] works 8821 return this.name && !jQuery( this ).is( ":disabled" ) && 8822 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && 8823 ( this.checked || !rcheckableType.test( type ) ); 8824 } ).map( function( _i, elem ) { 8825 var val = jQuery( this ).val(); 8826 8827 if ( val == null ) { 8828 return null; 8829 } 8830 8831 if ( Array.isArray( val ) ) { 8832 return jQuery.map( val, function( val ) { 8833 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 8834 } ); 8835 } 8836 8837 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; 8838 } ).get(); 8839 } 8840} ); 8841 8842 8843var 8844 r20 = /%20/g, 8845 rhash = /#.*$/, 8846 rantiCache = /([?&])_=[^&]*/, 8847 rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, 8848 8849 // trac-7653, trac-8125, trac-8152: local protocol detection 8850 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, 8851 rnoContent = /^(?:GET|HEAD)$/, 8852 rprotocol = /^\/\//, 8853 8854 /* Prefilters 8855 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) 8856 * 2) These are called: 8857 * - BEFORE asking for a transport 8858 * - AFTER param serialization (s.data is a string if s.processData is true) 8859 * 3) key is the dataType 8860 * 4) the catchall symbol "*" can be used 8861 * 5) execution will start with transport dataType and THEN continue down to "*" if needed 8862 */ 8863 prefilters = {}, 8864 8865 /* Transports bindings 8866 * 1) key is the dataType 8867 * 2) the catchall symbol "*" can be used 8868 * 3) selection will start with transport dataType and THEN go to "*" if needed 8869 */ 8870 transports = {}, 8871 8872 // Avoid comment-prolog char sequence (trac-10098); must appease lint and evade compression 8873 allTypes = "*/".concat( "*" ), 8874 8875 // Anchor tag for parsing the document origin 8876 originAnchor = document.createElement( "a" ); 8877 8878originAnchor.href = location.href; 8879 8880// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport 8881function addToPrefiltersOrTransports( structure ) { 8882 8883 // dataTypeExpression is optional and defaults to "*" 8884 return function( dataTypeExpression, func ) { 8885 8886 if ( typeof dataTypeExpression !== "string" ) { 8887 func = dataTypeExpression; 8888 dataTypeExpression = "*"; 8889 } 8890 8891 var dataType, 8892 i = 0, 8893 dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; 8894 8895 if ( isFunction( func ) ) { 8896 8897 // For each dataType in the dataTypeExpression 8898 while ( ( dataType = dataTypes[ i++ ] ) ) { 8899 8900 // Prepend if requested 8901 if ( dataType[ 0 ] === "+" ) { 8902 dataType = dataType.slice( 1 ) || "*"; 8903 ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); 8904 8905 // Otherwise append 8906 } else { 8907 ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); 8908 } 8909 } 8910 } 8911 }; 8912} 8913 8914// Base inspection function for prefilters and transports 8915function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { 8916 8917 var inspected = {}, 8918 seekingTransport = ( structure === transports ); 8919 8920 function inspect( dataType ) { 8921 var selected; 8922 inspected[ dataType ] = true; 8923 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { 8924 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); 8925 if ( typeof dataTypeOrTransport === "string" && 8926 !seekingTransport && !inspected[ dataTypeOrTransport ] ) { 8927 8928 options.dataTypes.unshift( dataTypeOrTransport ); 8929 inspect( dataTypeOrTransport ); 8930 return false; 8931 } else if ( seekingTransport ) { 8932 return !( selected = dataTypeOrTransport ); 8933 } 8934 } ); 8935 return selected; 8936 } 8937 8938 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); 8939} 8940 8941// A special extend for ajax options 8942// that takes "flat" options (not to be deep extended) 8943// Fixes trac-9887 8944function ajaxExtend( target, src ) { 8945 var key, deep, 8946 flatOptions = jQuery.ajaxSettings.flatOptions || {}; 8947 8948 for ( key in src ) { 8949 if ( src[ key ] !== undefined ) { 8950 ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; 8951 } 8952 } 8953 if ( deep ) { 8954 jQuery.extend( true, target, deep ); 8955 } 8956 8957 return target; 8958} 8959 8960/* Handles responses to an ajax request: 8961 * - finds the right dataType (mediates between content-type and expected dataType) 8962 * - returns the corresponding response 8963 */ 8964function ajaxHandleResponses( s, jqXHR, responses ) { 8965 8966 var ct, type, finalDataType, firstDataType, 8967 contents = s.contents, 8968 dataTypes = s.dataTypes; 8969 8970 // Remove auto dataType and get content-type in the process 8971 while ( dataTypes[ 0 ] === "*" ) { 8972 dataTypes.shift(); 8973 if ( ct === undefined ) { 8974 ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); 8975 } 8976 } 8977 8978 // Check if we're dealing with a known content-type 8979 if ( ct ) { 8980 for ( type in contents ) { 8981 if ( contents[ type ] && contents[ type ].test( ct ) ) { 8982 dataTypes.unshift( type ); 8983 break; 8984 } 8985 } 8986 } 8987 8988 // Check to see if we have a response for the expected dataType 8989 if ( dataTypes[ 0 ] in responses ) { 8990 finalDataType = dataTypes[ 0 ]; 8991 } else { 8992
vendor: 9,527 bytes, lines 8993-9368
8993 // Try convertible dataTypes 8994 for ( type in responses ) { 8995 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { 8996 finalDataType = type; 8997 break; 8998 } 8999 if ( !firstDataType ) { 9000 firstDataType = type; 9001 } 9002 } 9003 9004 // Or just use first one 9005 finalDataType = finalDataType || firstDataType; 9006 } 9007 9008 // If we found a dataType 9009 // We add the dataType to the list if needed 9010 // and return the corresponding response 9011 if ( finalDataType ) { 9012 if ( finalDataType !== dataTypes[ 0 ] ) { 9013 dataTypes.unshift( finalDataType ); 9014 } 9015 return responses[ finalDataType ]; 9016 } 9017} 9018 9019/* Chain conversions given the request and the original response 9020 * Also sets the responseXXX fields on the jqXHR instance 9021 */ 9022function ajaxConvert( s, response, jqXHR, isSuccess ) { 9023 var conv2, current, conv, tmp, prev, 9024 converters = {}, 9025 9026 // Work with a copy of dataTypes in case we need to modify it for conversion 9027 dataTypes = s.dataTypes.slice(); 9028 9029 // Create converters map with lowercased keys 9030 if ( dataTypes[ 1 ] ) { 9031 for ( conv in s.converters ) { 9032 converters[ conv.toLowerCase() ] = s.converters[ conv ]; 9033 } 9034 } 9035 9036 current = dataTypes.shift(); 9037 9038 // Convert to each sequential dataType 9039 while ( current ) { 9040 9041 if ( s.responseFields[ current ] ) { 9042 jqXHR[ s.responseFields[ current ] ] = response; 9043 } 9044 9045 // Apply the dataFilter if provided 9046 if ( !prev && isSuccess && s.dataFilter ) { 9047 response = s.dataFilter( response, s.dataType ); 9048 } 9049 9050 prev = current; 9051 current = dataTypes.shift(); 9052 9053 if ( current ) { 9054 9055 // There's only work to do if current dataType is non-auto 9056 if ( current === "*" ) { 9057 9058 current = prev; 9059 9060 // Convert response if prev dataType is non-auto and differs from current 9061 } else if ( prev !== "*" && prev !== current ) { 9062 9063 // Seek a direct converter 9064 conv = converters[ prev + " " + current ] || converters[ "* " + current ]; 9065 9066 // If none found, seek a pair 9067 if ( !conv ) { 9068 for ( conv2 in converters ) { 9069 9070 // If conv2 outputs current 9071 tmp = conv2.split( " " ); 9072 if ( tmp[ 1 ] === current ) { 9073 9074 // If prev can be converted to accepted input 9075 conv = converters[ prev + " " + tmp[ 0 ] ] || 9076 converters[ "* " + tmp[ 0 ] ]; 9077 if ( conv ) { 9078 9079 // Condense equivalence converters 9080 if ( conv === true ) { 9081 conv = converters[ conv2 ]; 9082 9083 // Otherwise, insert the intermediate dataType 9084 } else if ( converters[ conv2 ] !== true ) { 9085 current = tmp[ 0 ]; 9086 dataTypes.unshift( tmp[ 1 ] ); 9087 } 9088 break; 9089 } 9090 } 9091 } 9092 } 9093 9094 // Apply converter (if not an equivalence) 9095 if ( conv !== true ) { 9096 9097 // Unless errors are allowed to bubble, catch and return them 9098 if ( conv && s.throws ) { 9099 response = conv( response ); 9100 } else { 9101 try { 9102 response = conv( response ); 9103 } catch ( e ) { 9104 return { 9105 state: "parsererror", 9106 error: conv ? e : "No conversion from " + prev + " to " + current 9107 }; 9108 } 9109 } 9110 } 9111 } 9112 } 9113 } 9114 9115 return { state: "success", data: response }; 9116} 9117 9118jQuery.extend( { 9119 9120 // Counter for holding the number of active queries 9121 active: 0, 9122 9123 // Last-Modified header cache for next request 9124 lastModified: {}, 9125 etag: {}, 9126 9127 ajaxSettings: { 9128 url: location.href, 9129 type: "GET", 9130 isLocal: rlocalProtocol.test( location.protocol ), 9131 global: true, 9132 processData: true, 9133 async: true, 9134 contentType: "application/x-www-form-urlencoded; charset=UTF-8", 9135 9136 /* 9137 timeout: 0, 9138 data: null, 9139 dataType: null, 9140 username: null, 9141 password: null, 9142 cache: null, 9143 throws: false, 9144 traditional: false, 9145 headers: {}, 9146 */ 9147 9148 accepts: { 9149 "*": allTypes, 9150 text: "text/plain", 9151 html: "text/html", 9152 xml: "application/xml, text/xml", 9153 json: "application/json, text/javascript" 9154 }, 9155 9156 contents: { 9157 xml: /\bxml\b/, 9158 html: /\bhtml/, 9159 json: /\bjson\b/ 9160 }, 9161 9162 responseFields: { 9163 xml: "responseXML", 9164 text: "responseText", 9165 json: "responseJSON" 9166 }, 9167 9168 // Data converters 9169 // Keys separate source (or catchall "*") and destination types with a single space 9170 converters: { 9171 9172 // Convert anything to text 9173 "* text": String, 9174 9175 // Text to html (true = no transformation) 9176 "text html": true, 9177 9178 // Evaluate text as a json expression 9179 "text json": JSON.parse, 9180 9181 // Parse text as xml 9182 "text xml": jQuery.parseXML 9183 }, 9184 9185 // For options that shouldn't be deep extended: 9186 // you can add your own custom options here if 9187 // and when you create one that shouldn't be 9188 // deep extended (see ajaxExtend) 9189 flatOptions: { 9190 url: true, 9191 context: true 9192 } 9193 }, 9194 9195 // Creates a full fledged settings object into target 9196 // with both ajaxSettings and settings fields. 9197 // If target is omitted, writes into ajaxSettings. 9198 ajaxSetup: function( target, settings ) { 9199 return settings ? 9200 9201 // Building a settings object 9202 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : 9203 9204 // Extending ajaxSettings 9205 ajaxExtend( jQuery.ajaxSettings, target ); 9206 }, 9207 9208 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), 9209 ajaxTransport: addToPrefiltersOrTransports( transports ), 9210 9211 // Main method 9212 ajax: function( url, options ) { 9213 9214 // If url is an object, simulate pre-1.5 signature 9215 if ( typeof url === "object" ) { 9216 options = url; 9217 url = undefined; 9218 } 9219 9220 // Force options to be an object 9221 options = options || {}; 9222 9223 var transport, 9224 9225 // URL without anti-cache param 9226 cacheURL, 9227 9228 // Response headers 9229 responseHeadersString, 9230 responseHeaders, 9231 9232 // timeout handle 9233 timeoutTimer, 9234 9235 // Url cleanup var 9236 urlAnchor, 9237 9238 // Request state (becomes false upon send and true upon completion) 9239 completed, 9240 9241 // To know if global events are to be dispatched 9242 fireGlobals, 9243 9244 // Loop variable 9245 i, 9246 9247 // uncached part of the url 9248 uncached, 9249 9250 // Create the final options object 9251 s = jQuery.ajaxSetup( {}, options ), 9252 9253 // Callbacks context 9254 callbackContext = s.context || s, 9255 9256 // Context for global events is callbackContext if it is a DOM node or jQuery collection 9257 globalEventContext = s.context && 9258 ( callbackContext.nodeType || callbackContext.jquery ) ? 9259 jQuery( callbackContext ) : 9260 jQuery.event, 9261 9262 // Deferreds 9263 deferred = jQuery.Deferred(), 9264 completeDeferred = jQuery.Callbacks( "once memory" ), 9265 9266 // Status-dependent callbacks 9267 statusCode = s.statusCode || {}, 9268 9269 // Headers (they are sent all at once) 9270 requestHeaders = {}, 9271 requestHeadersNames = {}, 9272 9273 // Default abort message 9274 strAbort = "canceled", 9275 9276 // Fake xhr 9277 jqXHR = { 9278 readyState: 0, 9279 9280 // Builds headers hashtable if needed 9281 getResponseHeader: function( key ) { 9282 var match; 9283 if ( completed ) { 9284 if ( !responseHeaders ) { 9285 responseHeaders = {}; 9286 while ( ( match = rheaders.exec( responseHeadersString ) ) ) { 9287 responseHeaders[ match[ 1 ].toLowerCase() + " " ] = 9288 ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) 9289 .concat( match[ 2 ] ); 9290 } 9291 } 9292 match = responseHeaders[ key.toLowerCase() + " " ]; 9293 } 9294 return match == null ? null : match.join( ", " ); 9295 }, 9296 9297 // Raw string 9298 getAllResponseHeaders: function() { 9299 return completed ? responseHeadersString : null; 9300 }, 9301 9302 // Caches the header 9303 setRequestHeader: function( name, value ) { 9304 if ( completed == null ) { 9305 name = requestHeadersNames[ name.toLowerCase() ] = 9306 requestHeadersNames[ name.toLowerCase() ] || name; 9307 requestHeaders[ name ] = value; 9308 } 9309 return this; 9310 }, 9311 9312 // Overrides response content-type header 9313 overrideMimeType: function( type ) { 9314 if ( completed == null ) { 9315 s.mimeType = type; 9316 } 9317 return this; 9318 }, 9319 9320 // Status-dependent callbacks 9321 statusCode: function( map ) { 9322 var code; 9323 if ( map ) { 9324 if ( completed ) { 9325 9326 // Execute the appropriate callbacks 9327 jqXHR.always( map[ jqXHR.status ] ); 9328 } else { 9329 9330 // Lazy-add the new callbacks in a way that preserves old ones 9331 for ( code in map ) { 9332 statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; 9333 } 9334 } 9335 } 9336 return this; 9337 }, 9338 9339 // Cancel the request 9340 abort: function( statusText ) { 9341 var finalText = statusText || strAbort; 9342 if ( transport ) { 9343 transport.abort( finalText ); 9344 } 9345 done( 0, finalText ); 9346 return this; 9347 } 9348 }; 9349 9350 // Attach deferreds 9351 deferred.promise( jqXHR ); 9352 9353 // Add protocol if not provided (prefilters might expect it) 9354 // Handle falsy url in the settings object (trac-10093: consistency with old signature) 9355 // We also use the url parameter if available 9356 s.url = ( ( url || s.url || location.href ) + "" ) 9357 .replace( rprotocol, location.protocol + "//" ); 9358 9359 // Alias method option to type as per ticket trac-12004 9360 s.type = options.method || options.type || s.method || s.type; 9361 9362 // Extract dataTypes list 9363 s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; 9364 9365 // A cross-domain request is in order when the origin doesn't match the current origin. 9366 if ( s.crossDomain == null ) { 9367 urlAnchor = document.createElement( "a" ); 9368
vendor: 37,628 bytes, lines 9369-10722
9369 // Support: IE <=8 - 11, Edge 12 - 15 9370 // IE throws exception on accessing the href property if url is malformed, 9371 // e.g. http://example.com:80x/ 9372 try { 9373 urlAnchor.href = s.url; 9374 9375 // Support: IE <=8 - 11 only 9376 // Anchor's host property isn't correctly set when s.url is relative 9377 urlAnchor.href = urlAnchor.href; 9378 s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== 9379 urlAnchor.protocol + "//" + urlAnchor.host; 9380 } catch ( e ) { 9381 9382 // If there is an error parsing the URL, assume it is crossDomain, 9383 // it can be rejected by the transport if it is invalid 9384 s.crossDomain = true; 9385 } 9386 } 9387 9388 // Convert data if not already a string 9389 if ( s.data && s.processData && typeof s.data !== "string" ) { 9390 s.data = jQuery.param( s.data, s.traditional ); 9391 } 9392 9393 // Apply prefilters 9394 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); 9395 9396 // If request was aborted inside a prefilter, stop there 9397 if ( completed ) { 9398 return jqXHR; 9399 } 9400 9401 // We can fire global events as of now if asked to 9402 // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (trac-15118) 9403 fireGlobals = jQuery.event && s.global; 9404 9405 // Watch for a new set of requests 9406 if ( fireGlobals && jQuery.active++ === 0 ) { 9407 jQuery.event.trigger( "ajaxStart" ); 9408 } 9409 9410 // Uppercase the type 9411 s.type = s.type.toUpperCase(); 9412 9413 // Determine if request has content 9414 s.hasContent = !rnoContent.test( s.type ); 9415 9416 // Save the URL in case we're toying with the If-Modified-Since 9417 // and/or If-None-Match header later on 9418 // Remove hash to simplify url manipulation 9419 cacheURL = s.url.replace( rhash, "" ); 9420 9421 // More options handling for requests with no content 9422 if ( !s.hasContent ) { 9423 9424 // Remember the hash so we can put it back 9425 uncached = s.url.slice( cacheURL.length ); 9426 9427 // If data is available and should be processed, append data to url 9428 if ( s.data && ( s.processData || typeof s.data === "string" ) ) { 9429 cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; 9430 9431 // trac-9682: remove data so that it's not used in an eventual retry 9432 delete s.data; 9433 } 9434 9435 // Add or update anti-cache param if needed 9436 if ( s.cache === false ) { 9437 cacheURL = cacheURL.replace( rantiCache, "$1" ); 9438 uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + 9439 uncached; 9440 } 9441 9442 // Put hash and anti-cache on the URL that will be requested (gh-1732) 9443 s.url = cacheURL + uncached; 9444 9445 // Change '%20' to '+' if this is encoded form body content (gh-2658) 9446 } else if ( s.data && s.processData && 9447 ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { 9448 s.data = s.data.replace( r20, "+" ); 9449 } 9450 9451 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 9452 if ( s.ifModified ) { 9453 if ( jQuery.lastModified[ cacheURL ] ) { 9454 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); 9455 } 9456 if ( jQuery.etag[ cacheURL ] ) { 9457 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); 9458 } 9459 } 9460 9461 // Set the correct header, if data is being sent 9462 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { 9463 jqXHR.setRequestHeader( "Content-Type", s.contentType ); 9464 } 9465 9466 // Set the Accepts header for the server, depending on the dataType 9467 jqXHR.setRequestHeader( 9468 "Accept", 9469 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? 9470 s.accepts[ s.dataTypes[ 0 ] ] + 9471 ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : 9472 s.accepts[ "*" ] 9473 ); 9474 9475 // Check for headers option 9476 for ( i in s.headers ) { 9477 jqXHR.setRequestHeader( i, s.headers[ i ] ); 9478 } 9479 9480 // Allow custom headers/mimetypes and early abort 9481 if ( s.beforeSend && 9482 ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { 9483 9484 // Abort if not done already and return 9485 return jqXHR.abort(); 9486 } 9487 9488 // Aborting is no longer a cancellation 9489 strAbort = "abort"; 9490 9491 // Install callbacks on deferreds 9492 completeDeferred.add( s.complete ); 9493 jqXHR.done( s.success ); 9494 jqXHR.fail( s.error ); 9495 9496 // Get transport 9497 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); 9498 9499 // If no transport, we auto-abort 9500 if ( !transport ) { 9501 done( -1, "No Transport" ); 9502 } else { 9503 jqXHR.readyState = 1; 9504 9505 // Send global event 9506 if ( fireGlobals ) { 9507 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); 9508 } 9509 9510 // If request was aborted inside ajaxSend, stop there 9511 if ( completed ) { 9512 return jqXHR; 9513 } 9514 9515 // Timeout 9516 if ( s.async && s.timeout > 0 ) { 9517 timeoutTimer = window.setTimeout( function() { 9518 jqXHR.abort( "timeout" ); 9519 }, s.timeout ); 9520 } 9521 9522 try { 9523 completed = false; 9524 transport.send( requestHeaders, done ); 9525 } catch ( e ) { 9526 9527 // Rethrow post-completion exceptions 9528 if ( completed ) { 9529 throw e; 9530 } 9531 9532 // Propagate others as results 9533 done( -1, e ); 9534 } 9535 } 9536 9537 // Callback for when everything is done 9538 function done( status, nativeStatusText, responses, headers ) { 9539 var isSuccess, success, error, response, modified, 9540 statusText = nativeStatusText; 9541 9542 // Ignore repeat invocations 9543 if ( completed ) { 9544 return; 9545 } 9546 9547 completed = true; 9548 9549 // Clear timeout if it exists 9550 if ( timeoutTimer ) { 9551 window.clearTimeout( timeoutTimer ); 9552 } 9553 9554 // Dereference transport for early garbage collection 9555 // (no matter how long the jqXHR object will be used) 9556 transport = undefined; 9557 9558 // Cache response headers 9559 responseHeadersString = headers || ""; 9560 9561 // Set readyState 9562 jqXHR.readyState = status > 0 ? 4 : 0; 9563 9564 // Determine if successful 9565 isSuccess = status >= 200 && status < 300 || status === 304; 9566 9567 // Get response data 9568 if ( responses ) { 9569 response = ajaxHandleResponses( s, jqXHR, responses ); 9570 } 9571 9572 // Use a noop converter for missing script but not if jsonp 9573 if ( !isSuccess && 9574 jQuery.inArray( "script", s.dataTypes ) > -1 && 9575 jQuery.inArray( "json", s.dataTypes ) < 0 ) { 9576 s.converters[ "text script" ] = function() {}; 9577 } 9578 9579 // Convert no matter what (that way responseXXX fields are always set) 9580 response = ajaxConvert( s, response, jqXHR, isSuccess ); 9581 9582 // If successful, handle type chaining 9583 if ( isSuccess ) { 9584 9585 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. 9586 if ( s.ifModified ) { 9587 modified = jqXHR.getResponseHeader( "Last-Modified" ); 9588 if ( modified ) { 9589 jQuery.lastModified[ cacheURL ] = modified; 9590 } 9591 modified = jqXHR.getResponseHeader( "etag" ); 9592 if ( modified ) { 9593 jQuery.etag[ cacheURL ] = modified; 9594 } 9595 } 9596 9597 // if no content 9598 if ( status === 204 || s.type === "HEAD" ) { 9599 statusText = "nocontent"; 9600 9601 // if not modified 9602 } else if ( status === 304 ) { 9603 statusText = "notmodified"; 9604 9605 // If we have data, let's convert it 9606 } else { 9607 statusText = response.state; 9608 success = response.data; 9609 error = response.error; 9610 isSuccess = !error; 9611 } 9612 } else { 9613 9614 // Extract error from statusText and normalize for non-aborts 9615 error = statusText; 9616 if ( status || !statusText ) { 9617 statusText = "error"; 9618 if ( status < 0 ) { 9619 status = 0; 9620 } 9621 } 9622 } 9623 9624 // Set data for the fake xhr object 9625 jqXHR.status = status; 9626 jqXHR.statusText = ( nativeStatusText || statusText ) + ""; 9627 9628 // Success/Error 9629 if ( isSuccess ) { 9630 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); 9631 } else { 9632 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); 9633 } 9634 9635 // Status-dependent callbacks 9636 jqXHR.statusCode( statusCode ); 9637 statusCode = undefined; 9638 9639 if ( fireGlobals ) { 9640 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", 9641 [ jqXHR, s, isSuccess ? success : error ] ); 9642 } 9643 9644 // Complete 9645 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); 9646 9647 if ( fireGlobals ) { 9648 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); 9649 9650 // Handle the global AJAX counter 9651 if ( !( --jQuery.active ) ) { 9652 jQuery.event.trigger( "ajaxStop" ); 9653 } 9654 } 9655 } 9656 9657 return jqXHR; 9658 }, 9659 9660 getJSON: function( url, data, callback ) { 9661 return jQuery.get( url, data, callback, "json" ); 9662 }, 9663 9664 getScript: function( url, callback ) { 9665 return jQuery.get( url, undefined, callback, "script" ); 9666 } 9667} ); 9668 9669jQuery.each( [ "get", "post" ], function( _i, method ) { 9670 jQuery[ method ] = function( url, data, callback, type ) { 9671 9672 // Shift arguments if data argument was omitted 9673 if ( isFunction( data ) ) { 9674 type = type || callback; 9675 callback = data; 9676 data = undefined; 9677 } 9678 9679 // The url can be an options object (which then must have .url) 9680 return jQuery.ajax( jQuery.extend( { 9681 url: url, 9682 type: method, 9683 dataType: type, 9684 data: data, 9685 success: callback 9686 }, jQuery.isPlainObject( url ) && url ) ); 9687 }; 9688} ); 9689 9690jQuery.ajaxPrefilter( function( s ) { 9691 var i; 9692 for ( i in s.headers ) { 9693 if ( i.toLowerCase() === "content-type" ) { 9694 s.contentType = s.headers[ i ] || ""; 9695 } 9696 } 9697} ); 9698 9699 9700jQuery._evalUrl = function( url, options, doc ) { 9701 return jQuery.ajax( { 9702 url: url, 9703 9704 // Make this explicit, since user can override this through ajaxSetup (trac-11264) 9705 type: "GET", 9706 dataType: "script", 9707 cache: true, 9708 async: false, 9709 global: false, 9710 9711 // Only evaluate the response if it is successful (gh-4126) 9712 // dataFilter is not invoked for failure responses, so using it instead 9713 // of the default converter is kludgy but it works. 9714 converters: { 9715 "text script": function() {} 9716 }, 9717 dataFilter: function( response ) { 9718 jQuery.globalEval( response, options, doc ); 9719 } 9720 } ); 9721}; 9722 9723 9724jQuery.fn.extend( { 9725 wrapAll: function( html ) { 9726 var wrap; 9727 9728 if ( this[ 0 ] ) { 9729 if ( isFunction( html ) ) { 9730 html = html.call( this[ 0 ] ); 9731 } 9732 9733 // The elements to wrap the target around 9734 wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); 9735 9736 if ( this[ 0 ].parentNode ) { 9737 wrap.insertBefore( this[ 0 ] ); 9738 } 9739 9740 wrap.map( function() { 9741 var elem = this; 9742 9743 while ( elem.firstElementChild ) { 9744 elem = elem.firstElementChild; 9745 } 9746 9747 return elem; 9748 } ).append( this ); 9749 } 9750 9751 return this; 9752 }, 9753 9754 wrapInner: function( html ) { 9755 if ( isFunction( html ) ) { 9756 return this.each( function( i ) { 9757 jQuery( this ).wrapInner( html.call( this, i ) ); 9758 } ); 9759 } 9760 9761 return this.each( function() { 9762 var self = jQuery( this ), 9763 contents = self.contents(); 9764 9765 if ( contents.length ) { 9766 contents.wrapAll( html ); 9767 9768 } else { 9769 self.append( html ); 9770 } 9771 } ); 9772 }, 9773 9774 wrap: function( html ) { 9775 var htmlIsFunction = isFunction( html ); 9776 9777 return this.each( function( i ) { 9778 jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); 9779 } ); 9780 }, 9781 9782 unwrap: function( selector ) { 9783 this.parent( selector ).not( "body" ).each( function() { 9784 jQuery( this ).replaceWith( this.childNodes ); 9785 } ); 9786 return this; 9787 } 9788} ); 9789 9790 9791jQuery.expr.pseudos.hidden = function( elem ) { 9792 return !jQuery.expr.pseudos.visible( elem ); 9793}; 9794jQuery.expr.pseudos.visible = function( elem ) { 9795 return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); 9796}; 9797 9798 9799 9800 9801jQuery.ajaxSettings.xhr = function() { 9802 try { 9803 return new window.XMLHttpRequest(); 9804 } catch ( e ) {} 9805}; 9806 9807var xhrSuccessStatus = { 9808 9809 // File protocol always yields status code 0, assume 200 9810 0: 200, 9811 9812 // Support: IE <=9 only 9813 // trac-1450: sometimes IE returns 1223 when it should be 204 9814 1223: 204 9815 }, 9816 xhrSupported = jQuery.ajaxSettings.xhr(); 9817 9818support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); 9819support.ajax = xhrSupported = !!xhrSupported; 9820 9821jQuery.ajaxTransport( function( options ) { 9822 var callback, errorCallback; 9823 9824 // Cross domain only allowed if supported through XMLHttpRequest 9825 if ( support.cors || xhrSupported && !options.crossDomain ) { 9826 return { 9827 send: function( headers, complete ) { 9828 var i, 9829 xhr = options.xhr(); 9830 9831 xhr.open( 9832 options.type, 9833 options.url, 9834 options.async, 9835 options.username, 9836 options.password 9837 ); 9838 9839 // Apply custom fields if provided 9840 if ( options.xhrFields ) { 9841 for ( i in options.xhrFields ) { 9842 xhr[ i ] = options.xhrFields[ i ]; 9843 } 9844 } 9845 9846 // Override mime type if needed 9847 if ( options.mimeType && xhr.overrideMimeType ) { 9848 xhr.overrideMimeType( options.mimeType ); 9849 } 9850 9851 // X-Requested-With header 9852 // For cross-domain requests, seeing as conditions for a preflight are 9853 // akin to a jigsaw puzzle, we simply never set it to be sure. 9854 // (it can always be set on a per-request basis or even using ajaxSetup) 9855 // For same-domain requests, won't change header if already provided. 9856 if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { 9857 headers[ "X-Requested-With" ] = "XMLHttpRequest"; 9858 } 9859 9860 // Set headers 9861 for ( i in headers ) { 9862 xhr.setRequestHeader( i, headers[ i ] ); 9863 } 9864 9865 // Callback 9866 callback = function( type ) { 9867 return function() { 9868 if ( callback ) { 9869 callback = errorCallback = xhr.onload = 9870 xhr.onerror = xhr.onabort = xhr.ontimeout = 9871 xhr.onreadystatechange = null; 9872 9873 if ( type === "abort" ) { 9874 xhr.abort(); 9875 } else if ( type === "error" ) { 9876 9877 // Support: IE <=9 only 9878 // On a manual native abort, IE9 throws 9879 // errors on any property access that is not readyState 9880 if ( typeof xhr.status !== "number" ) { 9881 complete( 0, "error" ); 9882 } else { 9883 complete( 9884 9885 // File: protocol always yields status 0; see trac-8605, trac-14207 9886 xhr.status, 9887 xhr.statusText 9888 ); 9889 } 9890 } else { 9891 complete( 9892 xhrSuccessStatus[ xhr.status ] || xhr.status, 9893 xhr.statusText, 9894 9895 // Support: IE <=9 only 9896 // IE9 has no XHR2 but throws on binary (trac-11426) 9897 // For XHR2 non-text, let the caller handle it (gh-2498) 9898 ( xhr.responseType || "text" ) !== "text" || 9899 typeof xhr.responseText !== "string" ? 9900 { binary: xhr.response } : 9901 { text: xhr.responseText }, 9902 xhr.getAllResponseHeaders() 9903 ); 9904 } 9905 } 9906 }; 9907 }; 9908 9909 // Listen to events 9910 xhr.onload = callback(); 9911 errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); 9912 9913 // Support: IE 9 only 9914 // Use onreadystatechange to replace onabort 9915 // to handle uncaught aborts 9916 if ( xhr.onabort !== undefined ) { 9917 xhr.onabort = errorCallback; 9918 } else { 9919 xhr.onreadystatechange = function() { 9920 9921 // Check readyState before timeout as it changes 9922 if ( xhr.readyState === 4 ) { 9923 9924 // Allow onerror to be called first, 9925 // but that will not handle a native abort 9926 // Also, save errorCallback to a variable 9927 // as xhr.onerror cannot be accessed 9928 window.setTimeout( function() { 9929 if ( callback ) { 9930 errorCallback(); 9931 } 9932 } ); 9933 } 9934 }; 9935 } 9936 9937 // Create the abort callback 9938 callback = callback( "abort" ); 9939 9940 try { 9941 9942 // Do send the request (this may raise an exception) 9943 xhr.send( options.hasContent && options.data || null ); 9944 } catch ( e ) { 9945 9946 // trac-14683: Only rethrow if this hasn't been notified as an error yet 9947 if ( callback ) { 9948 throw e; 9949 } 9950 } 9951 }, 9952 9953 abort: function() { 9954 if ( callback ) { 9955 callback(); 9956 } 9957 } 9958 }; 9959 } 9960} ); 9961 9962 9963 9964 9965// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) 9966jQuery.ajaxPrefilter( function( s ) { 9967 if ( s.crossDomain ) { 9968 s.contents.script = false; 9969 } 9970} ); 9971 9972// Install script dataType 9973jQuery.ajaxSetup( { 9974 accepts: { 9975 script: "text/javascript, application/javascript, " + 9976 "application/ecmascript, application/x-ecmascript" 9977 }, 9978 contents: { 9979 script: /\b(?:java|ecma)script\b/ 9980 }, 9981 converters: { 9982 "text script": function( text ) { 9983 jQuery.globalEval( text ); 9984 return text; 9985 } 9986 } 9987} ); 9988 9989// Handle cache's special case and crossDomain 9990jQuery.ajaxPrefilter( "script", function( s ) { 9991 if ( s.cache === undefined ) { 9992 s.cache = false; 9993 } 9994 if ( s.crossDomain ) { 9995 s.type = "GET"; 9996 } 9997} ); 9998 9999// Bind script tag hack transport 10000jQuery.ajaxTransport( "script", function( s ) { 10001 10002 // This transport only deals with cross domain or forced-by-attrs requests 10003 if ( s.crossDomain || s.scriptAttrs ) { 10004 var script, callback; 10005 return { 10006 send: function( _, complete ) { 10007 script = jQuery( "<script>" ) 10008 .attr( s.scriptAttrs || {} ) 10009 .prop( { charset: s.scriptCharset, src: s.url } ) 10010 .on( "load error", callback = function( evt ) { 10011 script.remove(); 10012 callback = null; 10013 if ( evt ) { 10014 complete( evt.type === "error" ? 404 : 200, evt.type ); 10015 } 10016 } ); 10017 10018 // Use native DOM manipulation to avoid our domManip AJAX trickery 10019 document.head.appendChild( script[ 0 ] ); 10020 }, 10021 abort: function() { 10022 if ( callback ) { 10023 callback(); 10024 } 10025 } 10026 }; 10027 } 10028} ); 10029 10030 10031 10032 10033var oldCallbacks = [], 10034 rjsonp = /(=)\?(?=&|$)|\?\?/; 10035 10036// Default jsonp settings 10037jQuery.ajaxSetup( { 10038 jsonp: "callback", 10039 jsonpCallback: function() { 10040 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce.guid++ ) ); 10041 this[ callback ] = true; 10042 return callback; 10043 } 10044} ); 10045 10046// Detect, normalize options and install callbacks for jsonp requests 10047jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { 10048 10049 var callbackName, overwritten, responseContainer, 10050 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? 10051 "url" : 10052 typeof s.data === "string" && 10053 ( s.contentType || "" ) 10054 .indexOf( "application/x-www-form-urlencoded" ) === 0 && 10055 rjsonp.test( s.data ) && "data" 10056 ); 10057 10058 // Handle iff the expected data type is "jsonp" or we have a parameter to set 10059 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { 10060 10061 // Get callback name, remembering preexisting value associated with it 10062 callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ? 10063 s.jsonpCallback() : 10064 s.jsonpCallback; 10065 10066 // Insert callback into url or form data 10067 if ( jsonProp ) { 10068 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); 10069 } else if ( s.jsonp !== false ) { 10070 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; 10071 } 10072 10073 // Use data converter to retrieve json after script execution 10074 s.converters[ "script json" ] = function() { 10075 if ( !responseContainer ) { 10076 jQuery.error( callbackName + " was not called" ); 10077 } 10078 return responseContainer[ 0 ]; 10079 }; 10080 10081 // Force json dataType 10082 s.dataTypes[ 0 ] = "json"; 10083 10084 // Install callback 10085 overwritten = window[ callbackName ]; 10086 window[ callbackName ] = function() { 10087 responseContainer = arguments; 10088 }; 10089 10090 // Clean-up function (fires after converters) 10091 jqXHR.always( function() { 10092 10093 // If previous value didn't exist - remove it 10094 if ( overwritten === undefined ) { 10095 jQuery( window ).removeProp( callbackName ); 10096 10097 // Otherwise restore preexisting value 10098 } else { 10099 window[ callbackName ] = overwritten; 10100 } 10101 10102 // Save back as free 10103 if ( s[ callbackName ] ) { 10104 10105 // Make sure that re-using the options doesn't screw things around 10106 s.jsonpCallback = originalSettings.jsonpCallback; 10107 10108 // Save the callback name for future use 10109 oldCallbacks.push( callbackName ); 10110 } 10111 10112 // Call if it was a function and we have a response 10113 if ( responseContainer && isFunction( overwritten ) ) { 10114 overwritten( responseContainer[ 0 ] ); 10115 } 10116 10117 responseContainer = overwritten = undefined; 10118 } ); 10119 10120 // Delegate to script 10121 return "script"; 10122 } 10123} ); 10124 10125 10126 10127 10128// Support: Safari 8 only 10129// In Safari 8 documents created via document.implementation.createHTMLDocument 10130// collapse sibling forms: the second one becomes a child of the first one. 10131// Because of that, this security measure has to be disabled in Safari 8. 10132// https://bugs.webkit.org/show_bug.cgi?id=137337 10133support.createHTMLDocument = ( function() { 10134 var body = document.implementation.createHTMLDocument( "" ).body; 10135 body.innerHTML = "<form></form><form></form>"; 10136 return body.childNodes.length === 2; 10137} )(); 10138 10139 10140// Argument "data" should be string of html 10141// context (optional): If specified, the fragment will be created in this context, 10142// defaults to document 10143// keepScripts (optional): If true, will include scripts passed in the html string 10144jQuery.parseHTML = function( data, context, keepScripts ) { 10145 if ( typeof data !== "string" ) { 10146 return []; 10147 } 10148 if ( typeof context === "boolean" ) { 10149 keepScripts = context; 10150 context = false; 10151 } 10152 10153 var base, parsed, scripts; 10154 10155 if ( !context ) { 10156 10157 // Stop scripts or inline event handlers from being executed immediately 10158 // by using document.implementation 10159 if ( support.createHTMLDocument ) { 10160 context = document.implementation.createHTMLDocument( "" ); 10161 10162 // Set the base href for the created document 10163 // so any parsed elements with URLs 10164 // are based on the document's URL (gh-2965) 10165 base = context.createElement( "base" ); 10166 base.href = document.location.href; 10167 context.head.appendChild( base ); 10168 } else { 10169 context = document; 10170 } 10171 } 10172 10173 parsed = rsingleTag.exec( data ); 10174 scripts = !keepScripts && []; 10175 10176 // Single tag 10177 if ( parsed ) { 10178 return [ context.createElement( parsed[ 1 ] ) ]; 10179 } 10180 10181 parsed = buildFragment( [ data ], context, scripts ); 10182 10183 if ( scripts && scripts.length ) { 10184 jQuery( scripts ).remove(); 10185 } 10186 10187 return jQuery.merge( [], parsed.childNodes ); 10188}; 10189 10190 10191/** 10192 * Load a url into a page 10193 */ 10194jQuery.fn.load = function( url, params, callback ) { 10195 var selector, type, response, 10196 self = this, 10197 off = url.indexOf( " " ); 10198 10199 if ( off > -1 ) { 10200 selector = stripAndCollapse( url.slice( off ) ); 10201 url = url.slice( 0, off ); 10202 } 10203 10204 // If it's a function 10205 if ( isFunction( params ) ) { 10206 10207 // We assume that it's the callback 10208 callback = params; 10209 params = undefined; 10210 10211 // Otherwise, build a param string 10212 } else if ( params && typeof params === "object" ) { 10213 type = "POST"; 10214 } 10215 10216 // If we have elements to modify, make the request 10217 if ( self.length > 0 ) { 10218 jQuery.ajax( { 10219 url: url, 10220 10221 // If "type" variable is undefined, then "GET" method will be used. 10222 // Make value of this field explicit since 10223 // user can override it through ajaxSetup method 10224 type: type || "GET", 10225 dataType: "html", 10226 data: params 10227 } ).done( function( responseText ) { 10228 10229 // Save response for use in complete callback 10230 response = arguments; 10231 10232 self.html( selector ? 10233 10234 // If a selector was specified, locate the right elements in a dummy div 10235 // Exclude scripts to avoid IE 'Permission Denied' errors 10236 jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) : 10237 10238 // Otherwise use the full result 10239 responseText ); 10240 10241 // If the request succeeds, this function gets "data", "status", "jqXHR" 10242 // but they are ignored because response was set above. 10243 // If it fails, this function gets "jqXHR", "status", "error" 10244 } ).always( callback && function( jqXHR, status ) { 10245 self.each( function() { 10246 callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] ); 10247 } ); 10248 } ); 10249 } 10250 10251 return this; 10252}; 10253 10254 10255 10256 10257jQuery.expr.pseudos.animated = function( elem ) { 10258 return jQuery.grep( jQuery.timers, function( fn ) { 10259 return elem === fn.elem; 10260 } ).length; 10261}; 10262 10263 10264 10265 10266jQuery.offset = { 10267 setOffset: function( elem, options, i ) { 10268 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, 10269 position = jQuery.css( elem, "position" ), 10270 curElem = jQuery( elem ), 10271 props = {}; 10272 10273 // Set position first, in-case top/left are set even on static elem 10274 if ( position === "static" ) { 10275 elem.style.position = "relative"; 10276 } 10277 10278 curOffset = curElem.offset(); 10279 curCSSTop = jQuery.css( elem, "top" ); 10280 curCSSLeft = jQuery.css( elem, "left" ); 10281 calculatePosition = ( position === "absolute" || position === "fixed" ) && 10282 ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1; 10283 10284 // Need to be able to calculate position if either 10285 // top or left is auto and position is either absolute or fixed 10286 if ( calculatePosition ) { 10287 curPosition = curElem.position(); 10288 curTop = curPosition.top; 10289 curLeft = curPosition.left; 10290 10291 } else { 10292 curTop = parseFloat( curCSSTop ) || 0; 10293 curLeft = parseFloat( curCSSLeft ) || 0; 10294 } 10295 10296 if ( isFunction( options ) ) { 10297 10298 // Use jQuery.extend here to allow modification of coordinates argument (gh-1848) 10299 options = options.call( elem, i, jQuery.extend( {}, curOffset ) ); 10300 } 10301 10302 if ( options.top != null ) { 10303 props.top = ( options.top - curOffset.top ) + curTop; 10304 } 10305 if ( options.left != null ) { 10306 props.left = ( options.left - curOffset.left ) + curLeft; 10307 } 10308 10309 if ( "using" in options ) { 10310 options.using.call( elem, props ); 10311 10312 } else { 10313 curElem.css( props ); 10314 } 10315 } 10316}; 10317 10318jQuery.fn.extend( { 10319 10320 // offset() relates an element's border box to the document origin 10321 offset: function( options ) { 10322 10323 // Preserve chaining for setter 10324 if ( arguments.length ) { 10325 return options === undefined ? 10326 this : 10327 this.each( function( i ) { 10328 jQuery.offset.setOffset( this, options, i ); 10329 } ); 10330 } 10331 10332 var rect, win, 10333 elem = this[ 0 ]; 10334 10335 if ( !elem ) { 10336 return; 10337 } 10338 10339 // Return zeros for disconnected and hidden (display: none) elements (gh-2310) 10340 // Support: IE <=11 only 10341 // Running getBoundingClientRect on a 10342 // disconnected node in IE throws an error 10343 if ( !elem.getClientRects().length ) { 10344 return { top: 0, left: 0 }; 10345 } 10346 10347 // Get document-relative position by adding viewport scroll to viewport-relative gBCR 10348 rect = elem.getBoundingClientRect(); 10349 win = elem.ownerDocument.defaultView; 10350 return { 10351 top: rect.top + win.pageYOffset, 10352 left: rect.left + win.pageXOffset 10353 }; 10354 }, 10355 10356 // position() relates an element's margin box to its offset parent's padding box 10357 // This corresponds to the behavior of CSS absolute positioning 10358 position: function() { 10359 if ( !this[ 0 ] ) { 10360 return; 10361 } 10362 10363 var offsetParent, offset, doc, 10364 elem = this[ 0 ], 10365 parentOffset = { top: 0, left: 0 }; 10366 10367 // position:fixed elements are offset from the viewport, which itself always has zero offset 10368 if ( jQuery.css( elem, "position" ) === "fixed" ) { 10369 10370 // Assume position:fixed implies availability of getBoundingClientRect 10371 offset = elem.getBoundingClientRect(); 10372 10373 } else { 10374 offset = this.offset(); 10375 10376 // Account for the *real* offset parent, which can be the document or its root element 10377 // when a statically positioned element is identified 10378 doc = elem.ownerDocument; 10379 offsetParent = elem.offsetParent || doc.documentElement; 10380 while ( offsetParent && 10381 ( offsetParent === doc.body || offsetParent === doc.documentElement ) && 10382 jQuery.css( offsetParent, "position" ) === "static" ) { 10383 10384 offsetParent = offsetParent.parentNode; 10385 } 10386 if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) { 10387 10388 // Incorporate borders into its offset, since they are outside its content origin 10389 parentOffset = jQuery( offsetParent ).offset(); 10390 parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true ); 10391 parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true ); 10392 } 10393 } 10394 10395 // Subtract parent offsets and element margins 10396 return { 10397 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), 10398 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) 10399 }; 10400 }, 10401 10402 // This method will return documentElement in the following cases: 10403 // 1) For the element inside the iframe without offsetParent, this method will return 10404 // documentElement of the parent window 10405 // 2) For the hidden or detached element 10406 // 3) For body or html element, i.e. in case of the html node - it will return itself 10407 // 10408 // but those exceptions were never presented as a real life use-cases 10409 // and might be considered as more preferable results. 10410 // 10411 // This logic, however, is not guaranteed and can change at any point in the future 10412 offsetParent: function() { 10413 return this.map( function() { 10414 var offsetParent = this.offsetParent; 10415 10416 while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) { 10417 offsetParent = offsetParent.offsetParent; 10418 } 10419 10420 return offsetParent || documentElement; 10421 } ); 10422 } 10423} ); 10424 10425// Create scrollLeft and scrollTop methods 10426jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) { 10427 var top = "pageYOffset" === prop; 10428 10429 jQuery.fn[ method ] = function( val ) { 10430 return access( this, function( elem, method, val ) { 10431 10432 // Coalesce documents and windows 10433 var win; 10434 if ( isWindow( elem ) ) { 10435 win = elem; 10436 } else if ( elem.nodeType === 9 ) { 10437 win = elem.defaultView; 10438 } 10439 10440 if ( val === undefined ) { 10441 return win ? win[ prop ] : elem[ method ]; 10442 } 10443 10444 if ( win ) { 10445 win.scrollTo( 10446 !top ? val : win.pageXOffset, 10447 top ? val : win.pageYOffset 10448 ); 10449 10450 } else { 10451 elem[ method ] = val; 10452 } 10453 }, method, val, arguments.length ); 10454 }; 10455} ); 10456 10457// Support: Safari <=7 - 9.1, Chrome <=37 - 49 10458// Add the top/left cssHooks using jQuery.fn.position 10459// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 10460// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347 10461// getComputedStyle returns percent when specified for top/left/bottom/right; 10462// rather than make the css module depend on the offset module, just check for it here 10463jQuery.each( [ "top", "left" ], function( _i, prop ) { 10464 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, 10465 function( elem, computed ) { 10466 if ( computed ) { 10467 computed = curCSS( elem, prop ); 10468 10469 // If curCSS returns percentage, fallback to offset 10470 return rnumnonpx.test( computed ) ? 10471 jQuery( elem ).position()[ prop ] + "px" : 10472 computed; 10473 } 10474 } 10475 ); 10476} ); 10477 10478 10479// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods 10480jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { 10481 jQuery.each( { 10482 padding: "inner" + name, 10483 content: type, 10484 "": "outer" + name 10485 }, function( defaultExtra, funcName ) { 10486 10487 // Margin is only for outerHeight, outerWidth 10488 jQuery.fn[ funcName ] = function( margin, value ) { 10489 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), 10490 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); 10491 10492 return access( this, function( elem, type, value ) { 10493 var doc; 10494 10495 if ( isWindow( elem ) ) { 10496 10497 // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729) 10498 return funcName.indexOf( "outer" ) === 0 ? 10499 elem[ "inner" + name ] : 10500 elem.document.documentElement[ "client" + name ]; 10501 } 10502 10503 // Get document width or height 10504 if ( elem.nodeType === 9 ) { 10505 doc = elem.documentElement; 10506 10507 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], 10508 // whichever is greatest 10509 return Math.max( 10510 elem.body[ "scroll" + name ], doc[ "scroll" + name ], 10511 elem.body[ "offset" + name ], doc[ "offset" + name ], 10512 doc[ "client" + name ] 10513 ); 10514 } 10515 10516 return value === undefined ? 10517 10518 // Get width or height on the element, requesting but not forcing parseFloat 10519 jQuery.css( elem, type, extra ) : 10520 10521 // Set width or height on the element 10522 jQuery.style( elem, type, value, extra ); 10523 }, type, chainable ? margin : undefined, chainable ); 10524 }; 10525 } ); 10526} ); 10527 10528 10529jQuery.each( [ 10530 "ajaxStart", 10531 "ajaxStop", 10532 "ajaxComplete", 10533 "ajaxError", 10534 "ajaxSuccess", 10535 "ajaxSend" 10536], function( _i, type ) { 10537 jQuery.fn[ type ] = function( fn ) { 10538 return this.on( type, fn ); 10539 }; 10540} ); 10541 10542 10543 10544 10545jQuery.fn.extend( { 10546 10547 bind: function( types, data, fn ) { 10548 return this.on( types, null, data, fn ); 10549 }, 10550 unbind: function( types, fn ) { 10551 return this.off( types, null, fn ); 10552 }, 10553 10554 delegate: function( selector, types, data, fn ) { 10555 return this.on( types, selector, data, fn ); 10556 }, 10557 undelegate: function( selector, types, fn ) { 10558 10559 // ( namespace ) or ( selector, types [, fn] ) 10560 return arguments.length === 1 ? 10561 this.off( selector, "**" ) : 10562 this.off( types, selector || "**", fn ); 10563 }, 10564 10565 hover: function( fnOver, fnOut ) { 10566 return this 10567 .on( "mouseenter", fnOver ) 10568 .on( "mouseleave", fnOut || fnOver ); 10569 } 10570} ); 10571 10572jQuery.each( 10573 ( "blur focus focusin focusout resize scroll click dblclick " + 10574 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + 10575 "change select submit keydown keypress keyup contextmenu" ).split( " " ), 10576 function( _i, name ) { 10577 10578 // Handle event binding 10579 jQuery.fn[ name ] = function( data, fn ) { 10580 return arguments.length > 0 ? 10581 this.on( name, null, data, fn ) : 10582 this.trigger( name ); 10583 }; 10584 } 10585); 10586 10587 10588 10589 10590// Support: Android <=4.0 only 10591// Make sure we trim BOM and NBSP 10592// Require that the "whitespace run" starts from a non-whitespace 10593// to avoid O(N^2) behavior when the engine would try matching "\s+$" at each space position. 10594var rtrim = /^[\s\uFEFF\xA0]+|([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/g; 10595 10596// Bind a function to a context, optionally partially applying any 10597// arguments. 10598// jQuery.proxy is deprecated to promote standards (specifically Function#bind) 10599// However, it is not slated for removal any time soon 10600jQuery.proxy = function( fn, context ) { 10601 var tmp, args, proxy; 10602 10603 if ( typeof context === "string" ) { 10604 tmp = fn[ context ]; 10605 context = fn; 10606 fn = tmp; 10607 } 10608 10609 // Quick check to determine if target is callable, in the spec 10610 // this throws a TypeError, but we will just return undefined. 10611 if ( !isFunction( fn ) ) { 10612 return undefined; 10613 } 10614 10615 // Simulated bind 10616 args = slice.call( arguments, 2 ); 10617 proxy = function() { 10618 return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); 10619 }; 10620 10621 // Set the guid of unique handler to the same of original handler, so it can be removed 10622 proxy.guid = fn.guid = fn.guid || jQuery.guid++; 10623 10624 return proxy; 10625}; 10626 10627jQuery.holdReady = function( hold ) { 10628 if ( hold ) { 10629 jQuery.readyWait++; 10630 } else { 10631 jQuery.ready( true ); 10632 } 10633}; 10634jQuery.isArray = Array.isArray; 10635jQuery.parseJSON = JSON.parse; 10636jQuery.nodeName = nodeName; 10637jQuery.isFunction = isFunction; 10638jQuery.isWindow = isWindow; 10639jQuery.camelCase = camelCase; 10640jQuery.type = toType; 10641 10642jQuery.now = Date.now; 10643 10644jQuery.isNumeric = function( obj ) { 10645 10646 // As of jQuery 3.0, isNumeric is limited to 10647 // strings and numbers (primitives or objects) 10648 // that can be coerced to finite numbers (gh-2662) 10649 var type = jQuery.type( obj ); 10650 return ( type === "number" || type === "string" ) && 10651 10652 // parseFloat NaNs numeric-cast false positives ("") 10653 // ...but misinterprets leading-number strings, particularly hex literals ("0x...") 10654 // subtraction forces infinities to NaN 10655 !isNaN( obj - parseFloat( obj ) ); 10656}; 10657 10658jQuery.trim = function( text ) { 10659 return text == null ? 10660 "" : 10661 ( text + "" ).replace( rtrim, "$1" ); 10662}; 10663 10664 10665 10666// Register as a named AMD module, since jQuery can be concatenated with other 10667// files that may use define, but not via a proper concatenation script that 10668// understands anonymous AMD modules. A named AMD is safest and most robust 10669// way to register. Lowercase jquery is used because AMD module names are 10670// derived from file names, and jQuery is normally delivered in a lowercase 10671// file name. Do this after creating the global so that if an AMD module wants 10672// to call noConflict to hide this version of jQuery, it will work. 10673 10674// Note that for maximum portability, libraries that are not jQuery should 10675// declare themselves as anonymous modules, and avoid setting a global if an 10676// AMD loader is present. jQuery is a special case. For more information, see 10677// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon 10678 10679if ( typeof define === "function" && define.amd ) { 10680 define( "jquery", [], function() { 10681 return jQuery; 10682 } ); 10683} 10684 10685 10686 10687 10688var 10689 10690 // Map over jQuery in case of overwrite 10691 _jQuery = window.jQuery, 10692 10693 // Map over the $ in case of overwrite 10694 _$ = window.$; 10695 10696jQuery.noConflict = function( deep ) { 10697 if ( window.$ === jQuery ) { 10698 window.$ = _$; 10699 } 10700 10701 if ( deep && window.jQuery === jQuery ) { 10702 window.jQuery = _jQuery; 10703 } 10704 10705 return jQuery; 10706}; 10707 10708// Expose jQuery and $ identifiers, even in AMD 10709// (trac-7102#comment:10, https://github.com/jquery/jquery/pull/557) 10710// and CommonJS for browser emulators (trac-13566) 10711if ( typeof noGlobal === "undefined" ) { 10712 window.jQuery = window.$ = jQuery; 10713} 10714 10715 10716 10717 10718return jQuery; 10719} ); 10720; 10721/*! jQuery UI - v1.14.1 - 2024-10-30 10722* https://jqueryui.com
vendor: 498,311 bytes, lines 10723-27993
10723* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js 10724* Copyright OpenJS Foundation and other contributors; Licensed MIT */ 10725 10726( function( factory ) { 10727 "use strict"; 10728 10729 if ( typeof define === "function" && define.amd ) { 10730 10731 // AMD. Register as an anonymous module. 10732 define( [ "jquery" ], factory ); 10733 } else { 10734 10735 // Browser globals 10736 factory( jQuery ); 10737 } 10738} )( function( $ ) { 10739"use strict"; 10740 10741$.ui = $.ui || {}; 10742 10743var version = $.ui.version = "1.14.1"; 10744 10745 10746/*! 10747 * jQuery UI Widget 1.14.1 10748 * https://jqueryui.com 10749 * 10750 * Copyright OpenJS Foundation and other contributors 10751 * Released under the MIT license. 10752 * https://jquery.org/license 10753 */ 10754 10755//>>label: Widget 10756//>>group: Core 10757//>>description: Provides a factory for creating stateful widgets with a common API. 10758//>>docs: https://api.jqueryui.com/jQuery.widget/ 10759//>>demos: https://jqueryui.com/widget/ 10760 10761 10762var widgetUuid = 0; 10763var widgetHasOwnProperty = Array.prototype.hasOwnProperty; 10764var widgetSlice = Array.prototype.slice; 10765 10766$.cleanData = ( function( orig ) { 10767 return function( elems ) { 10768 var events, elem, i; 10769 for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) { 10770 10771 // Only trigger remove when necessary to save time 10772 events = $._data( elem, "events" ); 10773 if ( events && events.remove ) { 10774 $( elem ).triggerHandler( "remove" ); 10775 } 10776 } 10777 orig( elems ); 10778 }; 10779} )( $.cleanData ); 10780 10781$.widget = function( name, base, prototype ) { 10782 var existingConstructor, constructor, basePrototype; 10783 10784 // ProxiedPrototype allows the provided prototype to remain unmodified 10785 // so that it can be used as a mixin for multiple widgets (#8876) 10786 var proxiedPrototype = {}; 10787 10788 var namespace = name.split( "." )[ 0 ]; 10789 name = name.split( "." )[ 1 ]; 10790 if ( name === "__proto__" || name === "constructor" ) { 10791 return $.error( "Invalid widget name: " + name ); 10792 } 10793 var fullName = namespace + "-" + name; 10794 10795 if ( !prototype ) { 10796 prototype = base; 10797 base = $.Widget; 10798 } 10799 10800 if ( Array.isArray( prototype ) ) { 10801 prototype = $.extend.apply( null, [ {} ].concat( prototype ) ); 10802 } 10803 10804 // Create selector for plugin 10805 $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) { 10806 return !!$.data( elem, fullName ); 10807 }; 10808 10809 $[ namespace ] = $[ namespace ] || {}; 10810 existingConstructor = $[ namespace ][ name ]; 10811 constructor = $[ namespace ][ name ] = function( options, element ) { 10812 10813 // Allow instantiation without "new" keyword 10814 if ( !this || !this._createWidget ) { 10815 return new constructor( options, element ); 10816 } 10817 10818 // Allow instantiation without initializing for simple inheritance 10819 // must use "new" keyword (the code above always passes args) 10820 if ( arguments.length ) { 10821 this._createWidget( options, element ); 10822 } 10823 }; 10824 10825 // Extend with the existing constructor to carry over any static properties 10826 $.extend( constructor, existingConstructor, { 10827 version: prototype.version, 10828 10829 // Copy the object used to create the prototype in case we need to 10830 // redefine the widget later 10831 _proto: $.extend( {}, prototype ), 10832 10833 // Track widgets that inherit from this widget in case this widget is 10834 // redefined after a widget inherits from it 10835 _childConstructors: [] 10836 } ); 10837 10838 basePrototype = new base(); 10839 10840 // We need to make the options hash a property directly on the new instance 10841 // otherwise we'll modify the options hash on the prototype that we're 10842 // inheriting from 10843 basePrototype.options = $.widget.extend( {}, basePrototype.options ); 10844 $.each( prototype, function( prop, value ) { 10845 if ( typeof value !== "function" ) { 10846 proxiedPrototype[ prop ] = value; 10847 return; 10848 } 10849 proxiedPrototype[ prop ] = ( function() { 10850 function _super() { 10851 return base.prototype[ prop ].apply( this, arguments ); 10852 } 10853 10854 function _superApply( args ) { 10855 return base.prototype[ prop ].apply( this, args ); 10856 } 10857 10858 return function() { 10859 var __super = this._super; 10860 var __superApply = this._superApply; 10861 var returnValue; 10862 10863 this._super = _super; 10864 this._superApply = _superApply; 10865 10866 returnValue = value.apply( this, arguments ); 10867 10868 this._super = __super; 10869 this._superApply = __superApply; 10870 10871 return returnValue; 10872 }; 10873 } )(); 10874 } ); 10875 constructor.prototype = $.widget.extend( basePrototype, { 10876 10877 // TODO: remove support for widgetEventPrefix 10878 // always use the name + a colon as the prefix, e.g., draggable:start 10879 // don't prefix for widgets that aren't DOM-based 10880 widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name 10881 }, proxiedPrototype, { 10882 constructor: constructor, 10883 namespace: namespace, 10884 widgetName: name, 10885 widgetFullName: fullName 10886 } ); 10887 10888 // If this widget is being redefined then we need to find all widgets that 10889 // are inheriting from it and redefine all of them so that they inherit from 10890 // the new version of this widget. We're essentially trying to replace one 10891 // level in the prototype chain. 10892 if ( existingConstructor ) { 10893 $.each( existingConstructor._childConstructors, function( i, child ) { 10894 var childPrototype = child.prototype; 10895 10896 // Redefine the child widget using the same prototype that was 10897 // originally used, but inherit from the new version of the base 10898 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, 10899 child._proto ); 10900 } ); 10901 10902 // Remove the list of existing child constructors from the old constructor 10903 // so the old child constructors can be garbage collected 10904 delete existingConstructor._childConstructors; 10905 } else { 10906 base._childConstructors.push( constructor ); 10907 } 10908 10909 $.widget.bridge( name, constructor ); 10910 10911 return constructor; 10912}; 10913 10914$.widget.extend = function( target ) { 10915 var input = widgetSlice.call( arguments, 1 ); 10916 var inputIndex = 0; 10917 var inputLength = input.length; 10918 var key; 10919 var value; 10920 10921 for ( ; inputIndex < inputLength; inputIndex++ ) { 10922 for ( key in input[ inputIndex ] ) { 10923 value = input[ inputIndex ][ key ]; 10924 if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) { 10925 10926 // Clone objects 10927 if ( $.isPlainObject( value ) ) { 10928 target[ key ] = $.isPlainObject( target[ key ] ) ? 10929 $.widget.extend( {}, target[ key ], value ) : 10930 10931 // Don't extend strings, arrays, etc. with objects 10932 $.widget.extend( {}, value ); 10933 10934 // Copy everything else by reference 10935 } else { 10936 target[ key ] = value; 10937 } 10938 } 10939 } 10940 } 10941 return target; 10942}; 10943 10944$.widget.bridge = function( name, object ) { 10945 var fullName = object.prototype.widgetFullName || name; 10946 $.fn[ name ] = function( options ) { 10947 var isMethodCall = typeof options === "string"; 10948 var args = widgetSlice.call( arguments, 1 ); 10949 var returnValue = this; 10950 10951 if ( isMethodCall ) { 10952 10953 // If this is an empty collection, we need to have the instance method 10954 // return undefined instead of the jQuery instance 10955 if ( !this.length && options === "instance" ) { 10956 returnValue = undefined; 10957 } else { 10958 this.each( function() { 10959 var methodValue; 10960 var instance = $.data( this, fullName ); 10961 10962 if ( options === "instance" ) { 10963 returnValue = instance; 10964 return false; 10965 } 10966 10967 if ( !instance ) { 10968 return $.error( "cannot call methods on " + name + 10969 " prior to initialization; " + 10970 "attempted to call method '" + options + "'" ); 10971 } 10972 10973 if ( typeof instance[ options ] !== "function" || 10974 options.charAt( 0 ) === "_" ) { 10975 return $.error( "no such method '" + options + "' for " + name + 10976 " widget instance" ); 10977 } 10978 10979 methodValue = instance[ options ].apply( instance, args ); 10980 10981 if ( methodValue !== instance && methodValue !== undefined ) { 10982 returnValue = methodValue && methodValue.jquery ? 10983 returnValue.pushStack( methodValue.get() ) : 10984 methodValue; 10985 return false; 10986 } 10987 } ); 10988 } 10989 } else { 10990 10991 // Allow multiple hashes to be passed on init 10992 if ( args.length ) { 10993 options = $.widget.extend.apply( null, [ options ].concat( args ) ); 10994 } 10995 10996 this.each( function() { 10997 var instance = $.data( this, fullName ); 10998 if ( instance ) { 10999 instance.option( options || {} ); 11000 if ( instance._init ) { 11001 instance._init(); 11002 } 11003 } else { 11004 $.data( this, fullName, new object( options, this ) ); 11005 } 11006 } ); 11007 } 11008 11009 return returnValue; 11010 }; 11011}; 11012 11013$.Widget = function( /* options, element */ ) {}; 11014$.Widget._childConstructors = []; 11015 11016$.Widget.prototype = { 11017 widgetName: "widget", 11018 widgetEventPrefix: "", 11019 defaultElement: "<div>", 11020 11021 options: { 11022 classes: {}, 11023 disabled: false, 11024 11025 // Callbacks 11026 create: null 11027 }, 11028 11029 _createWidget: function( options, element ) { 11030 element = $( element || this.defaultElement || this )[ 0 ]; 11031 this.element = $( element ); 11032 this.uuid = widgetUuid++; 11033 this.eventNamespace = "." + this.widgetName + this.uuid; 11034 11035 this.bindings = $(); 11036 this.hoverable = $(); 11037 this.focusable = $(); 11038 this.classesElementLookup = {}; 11039 11040 if ( element !== this ) { 11041 $.data( element, this.widgetFullName, this ); 11042 this._on( true, this.element, { 11043 remove: function( event ) { 11044 if ( event.target === element ) { 11045 this.destroy(); 11046 } 11047 } 11048 } ); 11049 this.document = $( element.style ? 11050 11051 // Element within the document 11052 element.ownerDocument : 11053 11054 // Element is window or document 11055 element.document || element ); 11056 this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow ); 11057 } 11058 11059 this.options = $.widget.extend( {}, 11060 this.options, 11061 this._getCreateOptions(), 11062 options ); 11063 11064 this._create(); 11065 11066 if ( this.options.disabled ) { 11067 this._setOptionDisabled( this.options.disabled ); 11068 } 11069 11070 this._trigger( "create", null, this._getCreateEventData() ); 11071 this._init(); 11072 }, 11073 11074 _getCreateOptions: function() { 11075 return {}; 11076 }, 11077 11078 _getCreateEventData: $.noop, 11079 11080 _create: $.noop, 11081 11082 _init: $.noop, 11083 11084 destroy: function() { 11085 var that = this; 11086 11087 this._destroy(); 11088 $.each( this.classesElementLookup, function( key, value ) { 11089 that._removeClass( value, key ); 11090 } ); 11091 11092 // We can probably remove the unbind calls in 2.0 11093 // all event bindings should go through this._on() 11094 this.element 11095 .off( this.eventNamespace ) 11096 .removeData( this.widgetFullName ); 11097 this.widget() 11098 .off( this.eventNamespace ) 11099 .removeAttr( "aria-disabled" ); 11100 11101 // Clean up events and states 11102 this.bindings.off( this.eventNamespace ); 11103 }, 11104 11105 _destroy: $.noop, 11106 11107 widget: function() { 11108 return this.element; 11109 }, 11110 11111 option: function( key, value ) { 11112 var options = key; 11113 var parts; 11114 var curOption; 11115 var i; 11116 11117 if ( arguments.length === 0 ) { 11118 11119 // Don't return a reference to the internal hash 11120 return $.widget.extend( {}, this.options ); 11121 } 11122 11123 if ( typeof key === "string" ) { 11124 11125 // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 11126 options = {}; 11127 parts = key.split( "." ); 11128 key = parts.shift(); 11129 if ( parts.length ) { 11130 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); 11131 for ( i = 0; i < parts.length - 1; i++ ) { 11132 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; 11133 curOption = curOption[ parts[ i ] ]; 11134 } 11135 key = parts.pop(); 11136 if ( arguments.length === 1 ) { 11137 return curOption[ key ] === undefined ? null : curOption[ key ]; 11138 } 11139 curOption[ key ] = value; 11140 } else { 11141 if ( arguments.length === 1 ) { 11142 return this.options[ key ] === undefined ? null : this.options[ key ]; 11143 } 11144 options[ key ] = value; 11145 } 11146 } 11147 11148 this._setOptions( options ); 11149 11150 return this; 11151 }, 11152 11153 _setOptions: function( options ) { 11154 var key; 11155 11156 for ( key in options ) { 11157 this._setOption( key, options[ key ] ); 11158 } 11159 11160 return this; 11161 }, 11162 11163 _setOption: function( key, value ) { 11164 if ( key === "classes" ) { 11165 this._setOptionClasses( value ); 11166 } 11167 11168 this.options[ key ] = value; 11169 11170 if ( key === "disabled" ) { 11171 this._setOptionDisabled( value ); 11172 } 11173 11174 return this; 11175 }, 11176 11177 _setOptionClasses: function( value ) { 11178 var classKey, elements, currentElements; 11179 11180 for ( classKey in value ) { 11181 currentElements = this.classesElementLookup[ classKey ]; 11182 if ( value[ classKey ] === this.options.classes[ classKey ] || 11183 !currentElements || 11184 !currentElements.length ) { 11185 continue; 11186 } 11187 11188 // We are doing this to create a new jQuery object because the _removeClass() call 11189 // on the next line is going to destroy the reference to the current elements being 11190 // tracked. We need to save a copy of this collection so that we can add the new classes 11191 // below. 11192 elements = $( currentElements.get() ); 11193 this._removeClass( currentElements, classKey ); 11194 11195 // We don't use _addClass() here, because that uses this.options.classes 11196 // for generating the string of classes. We want to use the value passed in from 11197 // _setOption(), this is the new value of the classes option which was passed to 11198 // _setOption(). We pass this value directly to _classes(). 11199 elements.addClass( this._classes( { 11200 element: elements, 11201 keys: classKey, 11202 classes: value, 11203 add: true 11204 } ) ); 11205 } 11206 }, 11207 11208 _setOptionDisabled: function( value ) { 11209 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value ); 11210 11211 // If the widget is becoming disabled, then nothing is interactive 11212 if ( value ) { 11213 this._removeClass( this.hoverable, null, "ui-state-hover" ); 11214 this._removeClass( this.focusable, null, "ui-state-focus" ); 11215 } 11216 }, 11217 11218 enable: function() { 11219 return this._setOptions( { disabled: false } ); 11220 }, 11221 11222 disable: function() { 11223 return this._setOptions( { disabled: true } ); 11224 }, 11225 11226 _classes: function( options ) { 11227 var full = []; 11228 var that = this; 11229 11230 options = $.extend( { 11231 element: this.element, 11232 classes: this.options.classes || {} 11233 }, options ); 11234 11235 function bindRemoveEvent() { 11236 var nodesToBind = []; 11237 11238 options.element.each( function( _, element ) { 11239 var isTracked = $.map( that.classesElementLookup, function( elements ) { 11240 return elements; 11241 } ) 11242 .some( function( elements ) { 11243 return elements.is( element ); 11244 } ); 11245 11246 if ( !isTracked ) { 11247 nodesToBind.push( element ); 11248 } 11249 } ); 11250 11251 that._on( $( nodesToBind ), { 11252 remove: "_untrackClassesElement" 11253 } ); 11254 } 11255 11256 function processClassString( classes, checkOption ) { 11257 var current, i; 11258 for ( i = 0; i < classes.length; i++ ) { 11259 current = that.classesElementLookup[ classes[ i ] ] || $(); 11260 if ( options.add ) { 11261 bindRemoveEvent(); 11262 current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) ); 11263 } else { 11264 current = $( current.not( options.element ).get() ); 11265 } 11266 that.classesElementLookup[ classes[ i ] ] = current; 11267 full.push( classes[ i ] ); 11268 if ( checkOption && options.classes[ classes[ i ] ] ) { 11269 full.push( options.classes[ classes[ i ] ] ); 11270 } 11271 } 11272 } 11273 11274 if ( options.keys ) { 11275 processClassString( options.keys.match( /\S+/g ) || [], true ); 11276 } 11277 if ( options.extra ) { 11278 processClassString( options.extra.match( /\S+/g ) || [] ); 11279 } 11280 11281 return full.join( " " ); 11282 }, 11283 11284 _untrackClassesElement: function( event ) { 11285 var that = this; 11286 $.each( that.classesElementLookup, function( key, value ) { 11287 if ( $.inArray( event.target, value ) !== -1 ) { 11288 that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); 11289 } 11290 } ); 11291 11292 this._off( $( event.target ) ); 11293 }, 11294 11295 _removeClass: function( element, keys, extra ) { 11296 return this._toggleClass( element, keys, extra, false ); 11297 }, 11298 11299 _addClass: function( element, keys, extra ) { 11300 return this._toggleClass( element, keys, extra, true ); 11301 }, 11302 11303 _toggleClass: function( element, keys, extra, add ) { 11304 add = ( typeof add === "boolean" ) ? add : extra; 11305 var shift = ( typeof element === "string" || element === null ), 11306 options = { 11307 extra: shift ? keys : extra, 11308 keys: shift ? element : keys, 11309 element: shift ? this.element : element, 11310 add: add 11311 }; 11312 options.element.toggleClass( this._classes( options ), add ); 11313 return this; 11314 }, 11315 11316 _on: function( suppressDisabledCheck, element, handlers ) { 11317 var delegateElement; 11318 var instance = this; 11319 11320 // No suppressDisabledCheck flag, shuffle arguments 11321 if ( typeof suppressDisabledCheck !== "boolean" ) { 11322 handlers = element; 11323 element = suppressDisabledCheck; 11324 suppressDisabledCheck = false; 11325 } 11326 11327 // No element argument, shuffle and use this.element 11328 if ( !handlers ) { 11329 handlers = element; 11330 element = this.element; 11331 delegateElement = this.widget(); 11332 } else { 11333 element = delegateElement = $( element ); 11334 this.bindings = this.bindings.add( element ); 11335 } 11336 11337 $.each( handlers, function( event, handler ) { 11338 function handlerProxy() { 11339 11340 // Allow widgets to customize the disabled handling 11341 // - disabled as an array instead of boolean 11342 // - disabled class as method for disabling individual parts 11343 if ( !suppressDisabledCheck && 11344 ( instance.options.disabled === true || 11345 $( this ).hasClass( "ui-state-disabled" ) ) ) { 11346 return; 11347 } 11348 return ( typeof handler === "string" ? instance[ handler ] : handler ) 11349 .apply( instance, arguments ); 11350 } 11351 11352 // Copy the guid so direct unbinding works 11353 if ( typeof handler !== "string" ) { 11354 handlerProxy.guid = handler.guid = 11355 handler.guid || handlerProxy.guid || $.guid++; 11356 } 11357 11358 var match = event.match( /^([\w:-]*)\s*(.*)$/ ); 11359 var eventName = match[ 1 ] + instance.eventNamespace; 11360 var selector = match[ 2 ]; 11361 11362 if ( selector ) { 11363 delegateElement.on( eventName, selector, handlerProxy ); 11364 } else { 11365 element.on( eventName, handlerProxy ); 11366 } 11367 } ); 11368 }, 11369 11370 _off: function( element, eventName ) { 11371 eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) + 11372 this.eventNamespace; 11373 element.off( eventName ); 11374 11375 // Clear the stack to avoid memory leaks (#10056) 11376 this.bindings = $( this.bindings.not( element ).get() ); 11377 this.focusable = $( this.focusable.not( element ).get() ); 11378 this.hoverable = $( this.hoverable.not( element ).get() ); 11379 }, 11380 11381 _delay: function( handler, delay ) { 11382 function handlerProxy() { 11383 return ( typeof handler === "string" ? instance[ handler ] : handler ) 11384 .apply( instance, arguments ); 11385 } 11386 var instance = this; 11387 return setTimeout( handlerProxy, delay || 0 ); 11388 }, 11389 11390 _hoverable: function( element ) { 11391 this.hoverable = this.hoverable.add( element ); 11392 this._on( element, { 11393 mouseenter: function( event ) { 11394 this._addClass( $( event.currentTarget ), null, "ui-state-hover" ); 11395 }, 11396 mouseleave: function( event ) { 11397 this._removeClass( $( event.currentTarget ), null, "ui-state-hover" ); 11398 } 11399 } ); 11400 }, 11401 11402 _focusable: function( element ) { 11403 this.focusable = this.focusable.add( element ); 11404 this._on( element, { 11405 focusin: function( event ) { 11406 this._addClass( $( event.currentTarget ), null, "ui-state-focus" ); 11407 }, 11408 focusout: function( event ) { 11409 this._removeClass( $( event.currentTarget ), null, "ui-state-focus" ); 11410 } 11411 } ); 11412 }, 11413 11414 _trigger: function( type, event, data ) { 11415 var prop, orig; 11416 var callback = this.options[ type ]; 11417 11418 data = data || {}; 11419 event = $.Event( event ); 11420 event.type = ( type === this.widgetEventPrefix ? 11421 type : 11422 this.widgetEventPrefix + type ).toLowerCase(); 11423 11424 // The original event may come from any element 11425 // so we need to reset the target on the new event 11426 event.target = this.element[ 0 ]; 11427 11428 // Copy original event properties over to the new event 11429 orig = event.originalEvent; 11430 if ( orig ) { 11431 for ( prop in orig ) { 11432 if ( !( prop in event ) ) { 11433 event[ prop ] = orig[ prop ]; 11434 } 11435 } 11436 } 11437 11438 this.element.trigger( event, data ); 11439 return !( typeof callback === "function" && 11440 callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false || 11441 event.isDefaultPrevented() ); 11442 } 11443}; 11444 11445$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { 11446 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { 11447 if ( typeof options === "string" ) { 11448 options = { effect: options }; 11449 } 11450 11451 var hasOptions; 11452 var effectName = !options ? 11453 method : 11454 options === true || typeof options === "number" ? 11455 defaultEffect : 11456 options.effect || defaultEffect; 11457 11458 options = options || {}; 11459 if ( typeof options === "number" ) { 11460 options = { duration: options }; 11461 } else if ( options === true ) { 11462 options = {}; 11463 } 11464 11465 hasOptions = !$.isEmptyObject( options ); 11466 options.complete = callback; 11467 11468 if ( options.delay ) { 11469 element.delay( options.delay ); 11470 } 11471 11472 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { 11473 element[ method ]( options ); 11474 } else if ( effectName !== method && element[ effectName ] ) { 11475 element[ effectName ]( options.duration, options.easing, callback ); 11476 } else { 11477 element.queue( function( next ) { 11478 $( this )[ method ](); 11479 if ( callback ) { 11480 callback.call( element[ 0 ] ); 11481 } 11482 next(); 11483 } ); 11484 } 11485 }; 11486} ); 11487 11488var widget = $.widget; 11489 11490 11491/*! 11492 * jQuery UI Position 1.14.1 11493 * https://jqueryui.com 11494 * 11495 * Copyright OpenJS Foundation and other contributors 11496 * Released under the MIT license. 11497 * https://jquery.org/license 11498 * 11499 * https://api.jqueryui.com/position/ 11500 */ 11501 11502//>>label: Position 11503//>>group: Core 11504//>>description: Positions elements relative to other elements. 11505//>>docs: https://api.jqueryui.com/position/ 11506//>>demos: https://jqueryui.com/position/ 11507 11508 11509( function() { 11510var cachedScrollbarWidth, 11511 max = Math.max, 11512 abs = Math.abs, 11513 rhorizontal = /left|center|right/, 11514 rvertical = /top|center|bottom/, 11515 roffset = /[\+\-]\d+(\.[\d]+)?%?/, 11516 rposition = /^\w+/, 11517 rpercent = /%$/, 11518 _position = $.fn.position; 11519 11520function getOffsets( offsets, width, height ) { 11521 return [ 11522 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), 11523 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) 11524 ]; 11525} 11526 11527function parseCss( element, property ) { 11528 return parseInt( $.css( element, property ), 10 ) || 0; 11529} 11530 11531function isWindow( obj ) { 11532 return obj != null && obj === obj.window; 11533} 11534 11535function getDimensions( elem ) { 11536 var raw = elem[ 0 ]; 11537 if ( raw.nodeType === 9 ) { 11538 return { 11539 width: elem.width(), 11540 height: elem.height(), 11541 offset: { top: 0, left: 0 } 11542 }; 11543 } 11544 if ( isWindow( raw ) ) { 11545 return { 11546 width: elem.width(), 11547 height: elem.height(), 11548 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } 11549 }; 11550 } 11551 if ( raw.preventDefault ) { 11552 return { 11553 width: 0, 11554 height: 0, 11555 offset: { top: raw.pageY, left: raw.pageX } 11556 }; 11557 } 11558 return { 11559 width: elem.outerWidth(), 11560 height: elem.outerHeight(), 11561 offset: elem.offset() 11562 }; 11563} 11564 11565$.position = { 11566 scrollbarWidth: function() { 11567 if ( cachedScrollbarWidth !== undefined ) { 11568 return cachedScrollbarWidth; 11569 } 11570 var w1, w2, 11571 div = $( "<div style=" + 11572 "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" + 11573 "<div style='height:300px;width:auto;'></div></div>" ), 11574 innerDiv = div.children()[ 0 ]; 11575 11576 $( "body" ).append( div ); 11577 w1 = innerDiv.offsetWidth; 11578 div.css( "overflow", "scroll" ); 11579 11580 w2 = innerDiv.offsetWidth; 11581 11582 if ( w1 === w2 ) { 11583 w2 = div[ 0 ].clientWidth; 11584 } 11585 11586 div.remove(); 11587 11588 return ( cachedScrollbarWidth = w1 - w2 ); 11589 }, 11590 getScrollInfo: function( within ) { 11591 var overflowX = within.isWindow || within.isDocument ? "" : 11592 within.element.css( "overflow-x" ), 11593 overflowY = within.isWindow || within.isDocument ? "" : 11594 within.element.css( "overflow-y" ), 11595 hasOverflowX = overflowX === "scroll" || 11596 ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ), 11597 hasOverflowY = overflowY === "scroll" || 11598 ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight ); 11599 return { 11600 width: hasOverflowY ? $.position.scrollbarWidth() : 0, 11601 height: hasOverflowX ? $.position.scrollbarWidth() : 0 11602 }; 11603 }, 11604 getWithinInfo: function( element ) { 11605 var withinElement = $( element || window ), 11606 isElemWindow = isWindow( withinElement[ 0 ] ), 11607 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9, 11608 hasOffset = !isElemWindow && !isDocument; 11609 return { 11610 element: withinElement, 11611 isWindow: isElemWindow, 11612 isDocument: isDocument, 11613 offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 }, 11614 scrollLeft: withinElement.scrollLeft(), 11615 scrollTop: withinElement.scrollTop(), 11616 width: withinElement.outerWidth(), 11617 height: withinElement.outerHeight() 11618 }; 11619 } 11620}; 11621 11622$.fn.position = function( options ) { 11623 if ( !options || !options.of ) { 11624 return _position.apply( this, arguments ); 11625 } 11626 11627 // Make a copy, we don't want to modify arguments 11628 options = $.extend( {}, options ); 11629 11630 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, 11631 11632 // Make sure string options are treated as CSS selectors 11633 target = typeof options.of === "string" ? 11634 $( document ).find( options.of ) : 11635 $( options.of ), 11636 11637 within = $.position.getWithinInfo( options.within ), 11638 scrollInfo = $.position.getScrollInfo( within ), 11639 collision = ( options.collision || "flip" ).split( " " ), 11640 offsets = {}; 11641 11642 dimensions = getDimensions( target ); 11643 if ( target[ 0 ].preventDefault ) { 11644 11645 // Force left top to allow flipping 11646 options.at = "left top"; 11647 } 11648 targetWidth = dimensions.width; 11649 targetHeight = dimensions.height; 11650 targetOffset = dimensions.offset; 11651 11652 // Clone to reuse original targetOffset later 11653 basePosition = $.extend( {}, targetOffset ); 11654 11655 // Force my and at to have valid horizontal and vertical positions 11656 // if a value is missing or invalid, it will be converted to center 11657 $.each( [ "my", "at" ], function() { 11658 var pos = ( options[ this ] || "" ).split( " " ), 11659 horizontalOffset, 11660 verticalOffset; 11661 11662 if ( pos.length === 1 ) { 11663 pos = rhorizontal.test( pos[ 0 ] ) ? 11664 pos.concat( [ "center" ] ) : 11665 rvertical.test( pos[ 0 ] ) ? 11666 [ "center" ].concat( pos ) : 11667 [ "center", "center" ]; 11668 } 11669 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; 11670 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; 11671 11672 // Calculate offsets 11673 horizontalOffset = roffset.exec( pos[ 0 ] ); 11674 verticalOffset = roffset.exec( pos[ 1 ] ); 11675 offsets[ this ] = [ 11676 horizontalOffset ? horizontalOffset[ 0 ] : 0, 11677 verticalOffset ? verticalOffset[ 0 ] : 0 11678 ]; 11679 11680 // Reduce to just the positions without the offsets 11681 options[ this ] = [ 11682 rposition.exec( pos[ 0 ] )[ 0 ], 11683 rposition.exec( pos[ 1 ] )[ 0 ] 11684 ]; 11685 } ); 11686 11687 // Normalize collision option 11688 if ( collision.length === 1 ) { 11689 collision[ 1 ] = collision[ 0 ]; 11690 } 11691 11692 if ( options.at[ 0 ] === "right" ) { 11693 basePosition.left += targetWidth; 11694 } else if ( options.at[ 0 ] === "center" ) { 11695 basePosition.left += targetWidth / 2; 11696 } 11697 11698 if ( options.at[ 1 ] === "bottom" ) { 11699 basePosition.top += targetHeight; 11700 } else if ( options.at[ 1 ] === "center" ) { 11701 basePosition.top += targetHeight / 2; 11702 } 11703 11704 atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); 11705 basePosition.left += atOffset[ 0 ]; 11706 basePosition.top += atOffset[ 1 ]; 11707 11708 return this.each( function() { 11709 var collisionPosition, using, 11710 elem = $( this ), 11711 elemWidth = elem.outerWidth(), 11712 elemHeight = elem.outerHeight(), 11713 marginLeft = parseCss( this, "marginLeft" ), 11714 marginTop = parseCss( this, "marginTop" ), 11715 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + 11716 scrollInfo.width, 11717 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + 11718 scrollInfo.height, 11719 position = $.extend( {}, basePosition ), 11720 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); 11721 11722 if ( options.my[ 0 ] === "right" ) { 11723 position.left -= elemWidth; 11724 } else if ( options.my[ 0 ] === "center" ) { 11725 position.left -= elemWidth / 2; 11726 } 11727 11728 if ( options.my[ 1 ] === "bottom" ) { 11729 position.top -= elemHeight; 11730 } else if ( options.my[ 1 ] === "center" ) { 11731 position.top -= elemHeight / 2; 11732 } 11733 11734 position.left += myOffset[ 0 ]; 11735 position.top += myOffset[ 1 ]; 11736 11737 collisionPosition = { 11738 marginLeft: marginLeft, 11739 marginTop: marginTop 11740 }; 11741 11742 $.each( [ "left", "top" ], function( i, dir ) { 11743 if ( $.ui.position[ collision[ i ] ] ) { 11744 $.ui.position[ collision[ i ] ][ dir ]( position, { 11745 targetWidth: targetWidth, 11746 targetHeight: targetHeight, 11747 elemWidth: elemWidth, 11748 elemHeight: elemHeight, 11749 collisionPosition: collisionPosition, 11750 collisionWidth: collisionWidth, 11751 collisionHeight: collisionHeight, 11752 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], 11753 my: options.my, 11754 at: options.at, 11755 within: within, 11756 elem: elem 11757 } ); 11758 } 11759 } ); 11760 11761 if ( options.using ) { 11762 11763 // Adds feedback as second argument to using callback, if present 11764 using = function( props ) { 11765 var left = targetOffset.left - position.left, 11766 right = left + targetWidth - elemWidth, 11767 top = targetOffset.top - position.top, 11768 bottom = top + targetHeight - elemHeight, 11769 feedback = { 11770 target: { 11771 element: target, 11772 left: targetOffset.left, 11773 top: targetOffset.top, 11774 width: targetWidth, 11775 height: targetHeight 11776 }, 11777 element: { 11778 element: elem, 11779 left: position.left, 11780 top: position.top, 11781 width: elemWidth, 11782 height: elemHeight 11783 }, 11784 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", 11785 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" 11786 }; 11787 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { 11788 feedback.horizontal = "center"; 11789 } 11790 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { 11791 feedback.vertical = "middle"; 11792 } 11793 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { 11794 feedback.important = "horizontal"; 11795 } else { 11796 feedback.important = "vertical"; 11797 } 11798 options.using.call( this, props, feedback ); 11799 }; 11800 } 11801 11802 elem.offset( $.extend( position, { using: using } ) ); 11803 } ); 11804}; 11805 11806$.ui.position = { 11807 fit: { 11808 left: function( position, data ) { 11809 var within = data.within, 11810 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, 11811 outerWidth = within.width, 11812 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 11813 overLeft = withinOffset - collisionPosLeft, 11814 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, 11815 newOverRight; 11816 11817 // Element is wider than within 11818 if ( data.collisionWidth > outerWidth ) { 11819 11820 // Element is initially over the left side of within 11821 if ( overLeft > 0 && overRight <= 0 ) { 11822 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - 11823 withinOffset; 11824 position.left += overLeft - newOverRight; 11825 11826 // Element is initially over right side of within 11827 } else if ( overRight > 0 && overLeft <= 0 ) { 11828 position.left = withinOffset; 11829 11830 // Element is initially over both left and right sides of within 11831 } else { 11832 if ( overLeft > overRight ) { 11833 position.left = withinOffset + outerWidth - data.collisionWidth; 11834 } else { 11835 position.left = withinOffset; 11836 } 11837 } 11838 11839 // Too far left -> align with left edge 11840 } else if ( overLeft > 0 ) { 11841 position.left += overLeft; 11842 11843 // Too far right -> align with right edge 11844 } else if ( overRight > 0 ) { 11845 position.left -= overRight; 11846 11847 // Adjust based on position and margin 11848 } else { 11849 position.left = max( position.left - collisionPosLeft, position.left ); 11850 } 11851 }, 11852 top: function( position, data ) { 11853 var within = data.within, 11854 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, 11855 outerHeight = data.within.height, 11856 collisionPosTop = position.top - data.collisionPosition.marginTop, 11857 overTop = withinOffset - collisionPosTop, 11858 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, 11859 newOverBottom; 11860 11861 // Element is taller than within 11862 if ( data.collisionHeight > outerHeight ) { 11863 11864 // Element is initially over the top of within 11865 if ( overTop > 0 && overBottom <= 0 ) { 11866 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - 11867 withinOffset; 11868 position.top += overTop - newOverBottom; 11869 11870 // Element is initially over bottom of within 11871 } else if ( overBottom > 0 && overTop <= 0 ) { 11872 position.top = withinOffset; 11873 11874 // Element is initially over both top and bottom of within 11875 } else { 11876 if ( overTop > overBottom ) { 11877 position.top = withinOffset + outerHeight - data.collisionHeight; 11878 } else { 11879 position.top = withinOffset; 11880 } 11881 } 11882 11883 // Too far up -> align with top 11884 } else if ( overTop > 0 ) { 11885 position.top += overTop; 11886 11887 // Too far down -> align with bottom edge 11888 } else if ( overBottom > 0 ) { 11889 position.top -= overBottom; 11890 11891 // Adjust based on position and margin 11892 } else { 11893 position.top = max( position.top - collisionPosTop, position.top ); 11894 } 11895 } 11896 }, 11897 flip: { 11898 left: function( position, data ) { 11899 var within = data.within, 11900 withinOffset = within.offset.left + within.scrollLeft, 11901 outerWidth = within.width, 11902 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, 11903 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 11904 overLeft = collisionPosLeft - offsetLeft, 11905 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, 11906 myOffset = data.my[ 0 ] === "left" ? 11907 -data.elemWidth : 11908 data.my[ 0 ] === "right" ? 11909 data.elemWidth : 11910 0, 11911 atOffset = data.at[ 0 ] === "left" ? 11912 data.targetWidth : 11913 data.at[ 0 ] === "right" ? 11914 -data.targetWidth : 11915 0, 11916 offset = -2 * data.offset[ 0 ], 11917 newOverRight, 11918 newOverLeft; 11919 11920 if ( overLeft < 0 ) { 11921 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - 11922 outerWidth - withinOffset; 11923 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { 11924 position.left += myOffset + atOffset + offset; 11925 } 11926 } else if ( overRight > 0 ) { 11927 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + 11928 atOffset + offset - offsetLeft; 11929 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { 11930 position.left += myOffset + atOffset + offset; 11931 } 11932 } 11933 }, 11934 top: function( position, data ) { 11935 var within = data.within, 11936 withinOffset = within.offset.top + within.scrollTop, 11937 outerHeight = within.height, 11938 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, 11939 collisionPosTop = position.top - data.collisionPosition.marginTop, 11940 overTop = collisionPosTop - offsetTop, 11941 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, 11942 top = data.my[ 1 ] === "top", 11943 myOffset = top ? 11944 -data.elemHeight : 11945 data.my[ 1 ] === "bottom" ? 11946 data.elemHeight : 11947 0, 11948 atOffset = data.at[ 1 ] === "top" ? 11949 data.targetHeight : 11950 data.at[ 1 ] === "bottom" ? 11951 -data.targetHeight : 11952 0, 11953 offset = -2 * data.offset[ 1 ], 11954 newOverTop, 11955 newOverBottom; 11956 if ( overTop < 0 ) { 11957 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - 11958 outerHeight - withinOffset; 11959 if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) { 11960 position.top += myOffset + atOffset + offset; 11961 } 11962 } else if ( overBottom > 0 ) { 11963 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + 11964 offset - offsetTop; 11965 if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) { 11966 position.top += myOffset + atOffset + offset; 11967 } 11968 } 11969 } 11970 }, 11971 flipfit: { 11972 left: function() { 11973 $.ui.position.flip.left.apply( this, arguments ); 11974 $.ui.position.fit.left.apply( this, arguments ); 11975 }, 11976 top: function() { 11977 $.ui.position.flip.top.apply( this, arguments ); 11978 $.ui.position.fit.top.apply( this, arguments ); 11979 } 11980 } 11981}; 11982 11983} )(); 11984 11985var position = $.ui.position; 11986 11987 11988/*! 11989 * jQuery UI :data 1.14.1 11990 * https://jqueryui.com 11991 * 11992 * Copyright OpenJS Foundation and other contributors 11993 * Released under the MIT license. 11994 * https://jquery.org/license 11995 */ 11996 11997//>>label: :data Selector 11998//>>group: Core 11999//>>description: Selects elements which have data stored under the specified key. 12000//>>docs: https://api.jqueryui.com/data-selector/ 12001 12002 12003var data = $.extend( $.expr.pseudos, { 12004 data: $.expr.createPseudo( function( dataName ) { 12005 return function( elem ) { 12006 return !!$.data( elem, dataName ); 12007 }; 12008 } ) 12009} ); 12010 12011/*! 12012 * jQuery UI Disable Selection 1.14.1 12013 * https://jqueryui.com 12014 * 12015 * Copyright OpenJS Foundation and other contributors 12016 * Released under the MIT license. 12017 * https://jquery.org/license 12018 */ 12019 12020//>>label: disableSelection 12021//>>group: Core 12022//>>description: Disable selection of text content within the set of matched elements. 12023//>>docs: https://api.jqueryui.com/disableSelection/ 12024 12025// This file is deprecated 12026 12027var disableSelection = $.fn.extend( { 12028 disableSelection: ( function() { 12029 var eventType = "onselectstart" in document.createElement( "div" ) ? 12030 "selectstart" : 12031 "mousedown"; 12032 12033 return function() { 12034 return this.on( eventType + ".ui-disableSelection", function( event ) { 12035 event.preventDefault(); 12036 } ); 12037 }; 12038 } )(), 12039 12040 enableSelection: function() { 12041 return this.off( ".ui-disableSelection" ); 12042 } 12043} ); 12044 12045 12046 12047// Create a local jQuery because jQuery Color relies on it and the 12048// global may not exist with AMD and a custom build (#10199). 12049// This module is a noop if used as a regular AMD module. 12050// eslint-disable-next-line no-unused-vars 12051var jQuery = $; 12052 12053 12054/*! 12055 * jQuery Color Animations v3.0.0 12056 * https://github.com/jquery/jquery-color 12057 * 12058 * Copyright OpenJS Foundation and other contributors 12059 * Released under the MIT license. 12060 * https://jquery.org/license 12061 * 12062 * Date: Wed May 15 16:49:44 2024 +0200 12063 */ 12064 12065 12066 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " + 12067 "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", 12068 12069 class2type = {}, 12070 toString = class2type.toString, 12071 12072 // plusequals test for += 100 -= 100 12073 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, 12074 12075 // a set of RE's that can match strings and generate color tuples. 12076 stringParsers = [ { 12077 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 12078 parse: function( execResult ) { 12079 return [ 12080 execResult[ 1 ], 12081 execResult[ 2 ], 12082 execResult[ 3 ], 12083 execResult[ 4 ] 12084 ]; 12085 } 12086 }, { 12087 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 12088 parse: function( execResult ) { 12089 return [ 12090 execResult[ 1 ] * 2.55, 12091 execResult[ 2 ] * 2.55, 12092 execResult[ 3 ] * 2.55, 12093 execResult[ 4 ] 12094 ]; 12095 } 12096 }, { 12097 12098 // this regex ignores A-F because it's compared against an already lowercased string 12099 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/, 12100 parse: function( execResult ) { 12101 return [ 12102 parseInt( execResult[ 1 ], 16 ), 12103 parseInt( execResult[ 2 ], 16 ), 12104 parseInt( execResult[ 3 ], 16 ), 12105 execResult[ 4 ] ? 12106 ( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) : 12107 1 12108 ]; 12109 } 12110 }, { 12111 12112 // this regex ignores A-F because it's compared against an already lowercased string 12113 re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/, 12114 parse: function( execResult ) { 12115 return [ 12116 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), 12117 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), 12118 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ), 12119 execResult[ 4 ] ? 12120 ( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 ) 12121 .toFixed( 2 ) : 12122 1 12123 ]; 12124 } 12125 }, { 12126 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 12127 space: "hsla", 12128 parse: function( execResult ) { 12129 return [ 12130 execResult[ 1 ], 12131 execResult[ 2 ] / 100, 12132 execResult[ 3 ] / 100, 12133 execResult[ 4 ] 12134 ]; 12135 } 12136 } ], 12137 12138 // jQuery.Color( ) 12139 color = jQuery.Color = function( color, green, blue, alpha ) { 12140 return new jQuery.Color.fn.parse( color, green, blue, alpha ); 12141 }, 12142 spaces = { 12143 rgba: { 12144 props: { 12145 red: { 12146 idx: 0, 12147 type: "byte" 12148 }, 12149 green: { 12150 idx: 1, 12151 type: "byte" 12152 }, 12153 blue: { 12154 idx: 2, 12155 type: "byte" 12156 } 12157 } 12158 }, 12159 12160 hsla: { 12161 props: { 12162 hue: { 12163 idx: 0, 12164 type: "degrees" 12165 }, 12166 saturation: { 12167 idx: 1, 12168 type: "percent" 12169 }, 12170 lightness: { 12171 idx: 2, 12172 type: "percent" 12173 } 12174 } 12175 } 12176 }, 12177 propTypes = { 12178 "byte": { 12179 floor: true, 12180 max: 255 12181 }, 12182 "percent": { 12183 max: 1 12184 }, 12185 "degrees": { 12186 mod: 360, 12187 floor: true 12188 } 12189 }, 12190 12191 // colors = jQuery.Color.names 12192 colors, 12193 12194 // local aliases of functions called often 12195 each = jQuery.each; 12196 12197// define cache name and alpha properties 12198// for rgba and hsla spaces 12199each( spaces, function( spaceName, space ) { 12200 space.cache = "_" + spaceName; 12201 space.props.alpha = { 12202 idx: 3, 12203 type: "percent", 12204 def: 1 12205 }; 12206} ); 12207 12208// Populate the class2type map 12209jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), 12210 function( _i, name ) { 12211 class2type[ "[object " + name + "]" ] = name.toLowerCase(); 12212 } ); 12213 12214function getType( obj ) { 12215 if ( obj == null ) { 12216 return obj + ""; 12217 } 12218 12219 return typeof obj === "object" ? 12220 class2type[ toString.call( obj ) ] || "object" : 12221 typeof obj; 12222} 12223 12224function clamp( value, prop, allowEmpty ) { 12225 var type = propTypes[ prop.type ] || {}; 12226 12227 if ( value == null ) { 12228 return ( allowEmpty || !prop.def ) ? null : prop.def; 12229 } 12230 12231 // ~~ is an short way of doing floor for positive numbers 12232 value = type.floor ? ~~value : parseFloat( value ); 12233 12234 if ( type.mod ) { 12235 12236 // we add mod before modding to make sure that negatives values 12237 // get converted properly: -10 -> 350 12238 return ( value + type.mod ) % type.mod; 12239 } 12240 12241 // for now all property types without mod have min and max 12242 return Math.min( type.max, Math.max( 0, value ) ); 12243} 12244 12245function stringParse( string ) { 12246 var inst = color(), 12247 rgba = inst._rgba = []; 12248 12249 string = string.toLowerCase(); 12250 12251 each( stringParsers, function( _i, parser ) { 12252 var parsed, 12253 match = parser.re.exec( string ), 12254 values = match && parser.parse( match ), 12255 spaceName = parser.space || "rgba"; 12256 12257 if ( values ) { 12258 parsed = inst[ spaceName ]( values ); 12259 12260 // if this was an rgba parse the assignment might happen twice 12261 // oh well.... 12262 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; 12263 rgba = inst._rgba = parsed._rgba; 12264 12265 // exit each( stringParsers ) here because we matched 12266 return false; 12267 } 12268 } ); 12269 12270 // Found a stringParser that handled it 12271 if ( rgba.length ) { 12272 12273 // if this came from a parsed string, force "transparent" when alpha is 0 12274 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) 12275 if ( rgba.join() === "0,0,0,0" ) { 12276 jQuery.extend( rgba, colors.transparent ); 12277 } 12278 return inst; 12279 } 12280 12281 // named colors 12282 return colors[ string ]; 12283} 12284 12285color.fn = jQuery.extend( color.prototype, { 12286 parse: function( red, green, blue, alpha ) { 12287 if ( red === undefined ) { 12288 this._rgba = [ null, null, null, null ]; 12289 return this; 12290 } 12291 if ( red.jquery || red.nodeType ) { 12292 red = jQuery( red ).css( green ); 12293 green = undefined; 12294 } 12295 12296 var inst = this, 12297 type = getType( red ), 12298 rgba = this._rgba = []; 12299 12300 // more than 1 argument specified - assume ( red, green, blue, alpha ) 12301 if ( green !== undefined ) { 12302 red = [ red, green, blue, alpha ]; 12303 type = "array"; 12304 } 12305 12306 if ( type === "string" ) { 12307 return this.parse( stringParse( red ) || colors._default ); 12308 } 12309 12310 if ( type === "array" ) { 12311 each( spaces.rgba.props, function( _key, prop ) { 12312 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); 12313 } ); 12314 return this; 12315 } 12316 12317 if ( type === "object" ) { 12318 if ( red instanceof color ) { 12319 each( spaces, function( _spaceName, space ) { 12320 if ( red[ space.cache ] ) { 12321 inst[ space.cache ] = red[ space.cache ].slice(); 12322 } 12323 } ); 12324 } else { 12325 each( spaces, function( _spaceName, space ) { 12326 var cache = space.cache; 12327 each( space.props, function( key, prop ) { 12328 12329 // if the cache doesn't exist, and we know how to convert 12330 if ( !inst[ cache ] && space.to ) { 12331 12332 // if the value was null, we don't need to copy it 12333 // if the key was alpha, we don't need to copy it either 12334 if ( key === "alpha" || red[ key ] == null ) { 12335 return; 12336 } 12337 inst[ cache ] = space.to( inst._rgba ); 12338 } 12339 12340 // this is the only case where we allow nulls for ALL properties. 12341 // call clamp with alwaysAllowEmpty 12342 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); 12343 } ); 12344 12345 // everything defined but alpha? 12346 if ( inst[ cache ] && jQuery.inArray( 12347 null, 12348 inst[ cache ].slice( 0, 3 ) 12349 ) < 0 ) { 12350 12351 // use the default of 1 12352 if ( inst[ cache ][ 3 ] == null ) { 12353 inst[ cache ][ 3 ] = 1; 12354 } 12355 12356 if ( space.from ) { 12357 inst._rgba = space.from( inst[ cache ] ); 12358 } 12359 } 12360 } ); 12361 } 12362 return this; 12363 } 12364 }, 12365 is: function( compare ) { 12366 var is = color( compare ), 12367 same = true, 12368 inst = this; 12369 12370 each( spaces, function( _, space ) { 12371 var localCache, 12372 isCache = is[ space.cache ]; 12373 if ( isCache ) { 12374 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; 12375 each( space.props, function( _, prop ) { 12376 if ( isCache[ prop.idx ] != null ) { 12377 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); 12378 return same; 12379 } 12380 } ); 12381 } 12382 return same; 12383 } ); 12384 return same; 12385 }, 12386 _space: function() { 12387 var used = [], 12388 inst = this; 12389 each( spaces, function( spaceName, space ) { 12390 if ( inst[ space.cache ] ) { 12391 used.push( spaceName ); 12392 } 12393 } ); 12394 return used.pop(); 12395 }, 12396 transition: function( other, distance ) { 12397 var end = color( other ), 12398 spaceName = end._space(), 12399 space = spaces[ spaceName ], 12400 startColor = this.alpha() === 0 ? color( "transparent" ) : this, 12401 start = startColor[ space.cache ] || space.to( startColor._rgba ), 12402 result = start.slice(); 12403 12404 end = end[ space.cache ]; 12405 each( space.props, function( _key, prop ) { 12406 var index = prop.idx, 12407 startValue = start[ index ], 12408 endValue = end[ index ], 12409 type = propTypes[ prop.type ] || {}; 12410 12411 // if null, don't override start value 12412 if ( endValue === null ) { 12413 return; 12414 } 12415 12416 // if null - use end 12417 if ( startValue === null ) { 12418 result[ index ] = endValue; 12419 } else { 12420 if ( type.mod ) { 12421 if ( endValue - startValue > type.mod / 2 ) { 12422 startValue += type.mod; 12423 } else if ( startValue - endValue > type.mod / 2 ) { 12424 startValue -= type.mod; 12425 } 12426 } 12427 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); 12428 } 12429 } ); 12430 return this[ spaceName ]( result ); 12431 }, 12432 blend: function( opaque ) { 12433 12434 // if we are already opaque - return ourself 12435 if ( this._rgba[ 3 ] === 1 ) { 12436 return this; 12437 } 12438 12439 var rgb = this._rgba.slice(), 12440 a = rgb.pop(), 12441 blend = color( opaque )._rgba; 12442 12443 return color( jQuery.map( rgb, function( v, i ) { 12444 return ( 1 - a ) * blend[ i ] + a * v; 12445 } ) ); 12446 }, 12447 toRgbaString: function() { 12448 var prefix = "rgba(", 12449 rgba = jQuery.map( this._rgba, function( v, i ) { 12450 if ( v != null ) { 12451 return v; 12452 } 12453 return i > 2 ? 1 : 0; 12454 } ); 12455 12456 if ( rgba[ 3 ] === 1 ) { 12457 rgba.pop(); 12458 prefix = "rgb("; 12459 } 12460 12461 return prefix + rgba.join( ", " ) + ")"; 12462 }, 12463 toHslaString: function() { 12464 var prefix = "hsla(", 12465 hsla = jQuery.map( this.hsla(), function( v, i ) { 12466 if ( v == null ) { 12467 v = i > 2 ? 1 : 0; 12468 } 12469 12470 // catch 1 and 2 12471 if ( i && i < 3 ) { 12472 v = Math.round( v * 100 ) + "%"; 12473 } 12474 return v; 12475 } ); 12476 12477 if ( hsla[ 3 ] === 1 ) { 12478 hsla.pop(); 12479 prefix = "hsl("; 12480 } 12481 return prefix + hsla.join( ", " ) + ")"; 12482 }, 12483 toHexString: function( includeAlpha ) { 12484 var rgba = this._rgba.slice(), 12485 alpha = rgba.pop(); 12486 12487 if ( includeAlpha ) { 12488 rgba.push( ~~( alpha * 255 ) ); 12489 } 12490 12491 return "#" + jQuery.map( rgba, function( v ) { 12492 12493 // default to 0 when nulls exist 12494 return ( "0" + ( v || 0 ).toString( 16 ) ).substr( -2 ); 12495 } ).join( "" ); 12496 }, 12497 toString: function() { 12498 return this.toRgbaString(); 12499 } 12500} ); 12501color.fn.parse.prototype = color.fn; 12502 12503// hsla conversions adapted from: 12504// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 12505 12506function hue2rgb( p, q, h ) { 12507 h = ( h + 1 ) % 1; 12508 if ( h * 6 < 1 ) { 12509 return p + ( q - p ) * h * 6; 12510 } 12511 if ( h * 2 < 1 ) { 12512 return q; 12513 } 12514 if ( h * 3 < 2 ) { 12515 return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6; 12516 } 12517 return p; 12518} 12519 12520spaces.hsla.to = function( rgba ) { 12521 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { 12522 return [ null, null, null, rgba[ 3 ] ]; 12523 } 12524 var r = rgba[ 0 ] / 255, 12525 g = rgba[ 1 ] / 255, 12526 b = rgba[ 2 ] / 255, 12527 a = rgba[ 3 ], 12528 max = Math.max( r, g, b ), 12529 min = Math.min( r, g, b ), 12530 diff = max - min, 12531 add = max + min, 12532 l = add * 0.5, 12533 h, s; 12534 12535 if ( min === max ) { 12536 h = 0; 12537 } else if ( r === max ) { 12538 h = ( 60 * ( g - b ) / diff ) + 360; 12539 } else if ( g === max ) { 12540 h = ( 60 * ( b - r ) / diff ) + 120; 12541 } else { 12542 h = ( 60 * ( r - g ) / diff ) + 240; 12543 } 12544 12545 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% 12546 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) 12547 if ( diff === 0 ) { 12548 s = 0; 12549 } else if ( l <= 0.5 ) { 12550 s = diff / add; 12551 } else { 12552 s = diff / ( 2 - add ); 12553 } 12554 return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ]; 12555}; 12556 12557spaces.hsla.from = function( hsla ) { 12558 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { 12559 return [ null, null, null, hsla[ 3 ] ]; 12560 } 12561 var h = hsla[ 0 ] / 360, 12562 s = hsla[ 1 ], 12563 l = hsla[ 2 ], 12564 a = hsla[ 3 ], 12565 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, 12566 p = 2 * l - q; 12567 12568 return [ 12569 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), 12570 Math.round( hue2rgb( p, q, h ) * 255 ), 12571 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), 12572 a 12573 ]; 12574}; 12575 12576 12577each( spaces, function( spaceName, space ) { 12578 var props = space.props, 12579 cache = space.cache, 12580 to = space.to, 12581 from = space.from; 12582 12583 // makes rgba() and hsla() 12584 color.fn[ spaceName ] = function( value ) { 12585 12586 // generate a cache for this space if it doesn't exist 12587 if ( to && !this[ cache ] ) { 12588 this[ cache ] = to( this._rgba ); 12589 } 12590 if ( value === undefined ) { 12591 return this[ cache ].slice(); 12592 } 12593 12594 var ret, 12595 type = getType( value ), 12596 arr = ( type === "array" || type === "object" ) ? value : arguments, 12597 local = this[ cache ].slice(); 12598 12599 each( props, function( key, prop ) { 12600 var val = arr[ type === "object" ? key : prop.idx ]; 12601 if ( val == null ) { 12602 val = local[ prop.idx ]; 12603 } 12604 local[ prop.idx ] = clamp( val, prop ); 12605 } ); 12606 12607 if ( from ) { 12608 ret = color( from( local ) ); 12609 ret[ cache ] = local; 12610 return ret; 12611 } else { 12612 return color( local ); 12613 } 12614 }; 12615 12616 // makes red() green() blue() alpha() hue() saturation() lightness() 12617 each( props, function( key, prop ) { 12618 12619 // alpha is included in more than one space 12620 if ( color.fn[ key ] ) { 12621 return; 12622 } 12623 color.fn[ key ] = function( value ) { 12624 var local, cur, match, fn, 12625 vtype = getType( value ); 12626 12627 if ( key === "alpha" ) { 12628 fn = this._hsla ? "hsla" : "rgba"; 12629 } else { 12630 fn = spaceName; 12631 } 12632 local = this[ fn ](); 12633 cur = local[ prop.idx ]; 12634 12635 if ( vtype === "undefined" ) { 12636 return cur; 12637 } 12638 12639 if ( vtype === "function" ) { 12640 value = value.call( this, cur ); 12641 vtype = getType( value ); 12642 } 12643 if ( value == null && prop.empty ) { 12644 return this; 12645 } 12646 if ( vtype === "string" ) { 12647 match = rplusequals.exec( value ); 12648 if ( match ) { 12649 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); 12650 } 12651 } 12652 local[ prop.idx ] = value; 12653 return this[ fn ]( local ); 12654 }; 12655 } ); 12656} ); 12657 12658// add cssHook and .fx.step function for each named hook. 12659// accept a space separated string of properties 12660color.hook = function( hook ) { 12661 var hooks = hook.split( " " ); 12662 each( hooks, function( _i, hook ) { 12663 jQuery.cssHooks[ hook ] = { 12664 set: function( elem, value ) { 12665 var parsed; 12666 12667 if ( value !== "transparent" && 12668 ( getType( value ) !== "string" || 12669 ( parsed = stringParse( value ) ) ) ) { 12670 value = color( parsed || value ); 12671 value = value.toRgbaString(); 12672 } 12673 elem.style[ hook ] = value; 12674 } 12675 }; 12676 jQuery.fx.step[ hook ] = function( fx ) { 12677 if ( !fx.colorInit ) { 12678 fx.start = color( fx.elem, hook ); 12679 fx.end = color( fx.end ); 12680 fx.colorInit = true; 12681 } 12682 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); 12683 }; 12684 } ); 12685 12686}; 12687 12688color.hook( stepHooks ); 12689 12690jQuery.cssHooks.borderColor = { 12691 expand: function( value ) { 12692 var expanded = {}; 12693 12694 each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) { 12695 expanded[ "border" + part + "Color" ] = value; 12696 } ); 12697 return expanded; 12698 } 12699}; 12700 12701// Basic color names only. 12702// Usage of any of the other color names requires adding yourself or including 12703// jquery.color.svg-names.js. 12704colors = jQuery.Color.names = { 12705 12706 // 4.1. Basic color keywords 12707 aqua: "#00ffff", 12708 black: "#000000", 12709 blue: "#0000ff", 12710 fuchsia: "#ff00ff", 12711 gray: "#808080", 12712 green: "#008000", 12713 lime: "#00ff00", 12714 maroon: "#800000", 12715 navy: "#000080", 12716 olive: "#808000", 12717 purple: "#800080", 12718 red: "#ff0000", 12719 silver: "#c0c0c0", 12720 teal: "#008080", 12721 white: "#ffffff", 12722 yellow: "#ffff00", 12723 12724 // 4.2.3. "transparent" color keyword 12725 transparent: [ null, null, null, 0 ], 12726 12727 _default: "#ffffff" 12728}; 12729 12730 12731/*! 12732 * jQuery UI Effects 1.14.1 12733 * https://jqueryui.com 12734 * 12735 * Copyright OpenJS Foundation and other contributors 12736 * Released under the MIT license. 12737 * https://jquery.org/license 12738 */ 12739 12740//>>label: Effects Core 12741//>>group: Effects 12742/* eslint-disable max-len */ 12743//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects. 12744/* eslint-enable max-len */ 12745//>>docs: https://api.jqueryui.com/category/effects-core/ 12746//>>demos: https://jqueryui.com/effect/ 12747 12748 12749var dataSpace = "ui-effects-", 12750 dataSpaceStyle = "ui-effects-style", 12751 dataSpaceAnimated = "ui-effects-animated"; 12752 12753$.effects = { 12754 effect: {} 12755}; 12756 12757/******************************************************************************/ 12758/****************************** CLASS ANIMATIONS ******************************/ 12759/******************************************************************************/ 12760( function() { 12761 12762var classAnimationActions = [ "add", "remove", "toggle" ], 12763 shorthandStyles = { 12764 border: 1, 12765 borderBottom: 1, 12766 borderColor: 1, 12767 borderLeft: 1, 12768 borderRight: 1, 12769 borderTop: 1, 12770 borderWidth: 1, 12771 margin: 1, 12772 padding: 1 12773 }; 12774 12775$.each( 12776 [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], 12777 function( _, prop ) { 12778 $.fx.step[ prop ] = function( fx ) { 12779 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { 12780 jQuery.style( fx.elem, prop, fx.end ); 12781 fx.setAttr = true; 12782 } 12783 }; 12784 } 12785); 12786 12787function camelCase( string ) { 12788 return string.replace( /-([\da-z])/gi, function( all, letter ) { 12789 return letter.toUpperCase(); 12790 } ); 12791} 12792 12793function getElementStyles( elem ) { 12794 var key, len, 12795 style = elem.ownerDocument.defaultView.getComputedStyle( elem ), 12796 styles = {}; 12797 12798 len = style.length; 12799 while ( len-- ) { 12800 key = style[ len ]; 12801 if ( typeof style[ key ] === "string" ) { 12802 styles[ camelCase( key ) ] = style[ key ]; 12803 } 12804 } 12805 12806 return styles; 12807} 12808 12809function styleDifference( oldStyle, newStyle ) { 12810 var diff = {}, 12811 name, value; 12812 12813 for ( name in newStyle ) { 12814 value = newStyle[ name ]; 12815 if ( oldStyle[ name ] !== value ) { 12816 if ( !shorthandStyles[ name ] ) { 12817 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { 12818 diff[ name ] = value; 12819 } 12820 } 12821 } 12822 } 12823 12824 return diff; 12825} 12826 12827$.effects.animateClass = function( value, duration, easing, callback ) { 12828 var o = $.speed( duration, easing, callback ); 12829 12830 return this.queue( function() { 12831 var animated = $( this ), 12832 baseClass = animated.attr( "class" ) || "", 12833 applyClassChange, 12834 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; 12835 12836 // Map the animated objects to store the original styles. 12837 allAnimations = allAnimations.map( function() { 12838 var el = $( this ); 12839 return { 12840 el: el, 12841 start: getElementStyles( this ) 12842 }; 12843 } ); 12844 12845 // Apply class change 12846 applyClassChange = function() { 12847 $.each( classAnimationActions, function( i, action ) { 12848 if ( value[ action ] ) { 12849 animated[ action + "Class" ]( value[ action ] ); 12850 } 12851 } ); 12852 }; 12853 applyClassChange(); 12854 12855 // Map all animated objects again - calculate new styles and diff 12856 allAnimations = allAnimations.map( function() { 12857 this.end = getElementStyles( this.el[ 0 ] ); 12858 this.diff = styleDifference( this.start, this.end ); 12859 return this; 12860 } ); 12861 12862 // Apply original class 12863 animated.attr( "class", baseClass ); 12864 12865 // Map all animated objects again - this time collecting a promise 12866 allAnimations = allAnimations.map( function() { 12867 var styleInfo = this, 12868 dfd = $.Deferred(), 12869 opts = $.extend( {}, o, { 12870 queue: false, 12871 complete: function() { 12872 dfd.resolve( styleInfo ); 12873 } 12874 } ); 12875 12876 this.el.animate( this.diff, opts ); 12877 return dfd.promise(); 12878 } ); 12879 12880 // Once all animations have completed: 12881 $.when.apply( $, allAnimations.get() ).done( function() { 12882 12883 // Set the final class 12884 applyClassChange(); 12885 12886 // For each animated element, 12887 // clear all css properties that were animated 12888 $.each( arguments, function() { 12889 var el = this.el; 12890 $.each( this.diff, function( key ) { 12891 el.css( key, "" ); 12892 } ); 12893 } ); 12894 12895 // This is guarnteed to be there if you use jQuery.speed() 12896 // it also handles dequeuing the next anim... 12897 o.complete.call( animated[ 0 ] ); 12898 } ); 12899 } ); 12900}; 12901 12902$.fn.extend( { 12903 addClass: ( function( orig ) { 12904 return function( classNames, speed, easing, callback ) { 12905 return speed ? 12906 $.effects.animateClass.call( this, 12907 { add: classNames }, speed, easing, callback ) : 12908 orig.apply( this, arguments ); 12909 }; 12910 } )( $.fn.addClass ), 12911 12912 removeClass: ( function( orig ) { 12913 return function( classNames, speed, easing, callback ) { 12914 return arguments.length > 1 ? 12915 $.effects.animateClass.call( this, 12916 { remove: classNames }, speed, easing, callback ) : 12917 orig.apply( this, arguments ); 12918 }; 12919 } )( $.fn.removeClass ), 12920 12921 toggleClass: ( function( orig ) { 12922 return function( classNames, force, speed, easing, callback ) { 12923 if ( typeof force === "boolean" || force === undefined ) { 12924 if ( !speed ) { 12925 12926 // Without speed parameter 12927 return orig.apply( this, arguments ); 12928 } else { 12929 return $.effects.animateClass.call( this, 12930 ( force ? { add: classNames } : { remove: classNames } ), 12931 speed, easing, callback ); 12932 } 12933 } else { 12934 12935 // Without force parameter 12936 return $.effects.animateClass.call( this, 12937 { toggle: classNames }, force, speed, easing ); 12938 } 12939 }; 12940 } )( $.fn.toggleClass ), 12941 12942 switchClass: function( remove, add, speed, easing, callback ) { 12943 return $.effects.animateClass.call( this, { 12944 add: add, 12945 remove: remove 12946 }, speed, easing, callback ); 12947 } 12948} ); 12949 12950} )(); 12951 12952/******************************************************************************/ 12953/*********************************** EFFECTS **********************************/ 12954/******************************************************************************/ 12955 12956( function() { 12957 12958if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) { 12959 $.expr.pseudos.animated = ( function( orig ) { 12960 return function( elem ) { 12961 return !!$( elem ).data( dataSpaceAnimated ) || orig( elem ); 12962 }; 12963 } )( $.expr.pseudos.animated ); 12964} 12965 12966if ( $.uiBackCompat === true ) { 12967 $.extend( $.effects, { 12968 12969 // Saves a set of properties in a data storage 12970 save: function( element, set ) { 12971 var i = 0, length = set.length; 12972 for ( ; i < length; i++ ) { 12973 if ( set[ i ] !== null ) { 12974 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); 12975 } 12976 } 12977 }, 12978 12979 // Restores a set of previously saved properties from a data storage 12980 restore: function( element, set ) { 12981 var val, i = 0, length = set.length; 12982 for ( ; i < length; i++ ) { 12983 if ( set[ i ] !== null ) { 12984 val = element.data( dataSpace + set[ i ] ); 12985 element.css( set[ i ], val ); 12986 } 12987 } 12988 }, 12989 12990 setMode: function( el, mode ) { 12991 if ( mode === "toggle" ) { 12992 mode = el.is( ":hidden" ) ? "show" : "hide"; 12993 } 12994 return mode; 12995 }, 12996 12997 // Wraps the element around a wrapper that copies position properties 12998 createWrapper: function( element ) { 12999 13000 // If the element is already wrapped, return it 13001 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 13002 return element.parent(); 13003 } 13004 13005 // Wrap the element 13006 var props = { 13007 width: element.outerWidth( true ), 13008 height: element.outerHeight( true ), 13009 "float": element.css( "float" ) 13010 }, 13011 wrapper = $( "<div></div>" ) 13012 .addClass( "ui-effects-wrapper" ) 13013 .css( { 13014 fontSize: "100%", 13015 background: "transparent", 13016 border: "none", 13017 margin: 0, 13018 padding: 0 13019 } ), 13020 13021 // Store the size in case width/height are defined in % - Fixes #5245 13022 size = { 13023 width: element.width(), 13024 height: element.height() 13025 }, 13026 active = document.activeElement; 13027 13028 // Support: Firefox 13029 // Firefox incorrectly exposes anonymous content 13030 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 13031 try { 13032 // eslint-disable-next-line no-unused-expressions 13033 active.id; 13034 } catch ( e ) { 13035 active = document.body; 13036 } 13037 13038 element.wrap( wrapper ); 13039 13040 // Fixes #7595 - Elements lose focus when wrapped. 13041 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 13042 $( active ).trigger( "focus" ); 13043 } 13044 13045 // Hotfix for jQuery 1.4 since some change in wrap() seems to actually 13046 // lose the reference to the wrapped element 13047 wrapper = element.parent(); 13048 13049 // Transfer positioning properties to the wrapper 13050 if ( element.css( "position" ) === "static" ) { 13051 wrapper.css( { position: "relative" } ); 13052 element.css( { position: "relative" } ); 13053 } else { 13054 $.extend( props, { 13055 position: element.css( "position" ), 13056 zIndex: element.css( "z-index" ) 13057 } ); 13058 $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) { 13059 props[ pos ] = element.css( pos ); 13060 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { 13061 props[ pos ] = "auto"; 13062 } 13063 } ); 13064 element.css( { 13065 position: "relative", 13066 top: 0, 13067 left: 0, 13068 right: "auto", 13069 bottom: "auto" 13070 } ); 13071 } 13072 element.css( size ); 13073 13074 return wrapper.css( props ).show(); 13075 }, 13076 13077 removeWrapper: function( element ) { 13078 var active = document.activeElement; 13079 13080 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 13081 element.parent().replaceWith( element ); 13082 13083 // Fixes #7595 - Elements lose focus when wrapped. 13084 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 13085 $( active ).trigger( "focus" ); 13086 } 13087 } 13088 13089 return element; 13090 } 13091 } ); 13092} 13093 13094$.extend( $.effects, { 13095 version: "1.14.1", 13096 13097 define: function( name, mode, effect ) { 13098 if ( !effect ) { 13099 effect = mode; 13100 mode = "effect"; 13101 } 13102 13103 $.effects.effect[ name ] = effect; 13104 $.effects.effect[ name ].mode = mode; 13105 13106 return effect; 13107 }, 13108 13109 scaledDimensions: function( element, percent, direction ) { 13110 if ( percent === 0 ) { 13111 return { 13112 height: 0, 13113 width: 0, 13114 outerHeight: 0, 13115 outerWidth: 0 13116 }; 13117 } 13118 13119 var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1, 13120 y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1; 13121 13122 return { 13123 height: element.height() * y, 13124 width: element.width() * x, 13125 outerHeight: element.outerHeight() * y, 13126 outerWidth: element.outerWidth() * x 13127 }; 13128 13129 }, 13130 13131 clipToBox: function( animation ) { 13132 return { 13133 width: animation.clip.right - animation.clip.left, 13134 height: animation.clip.bottom - animation.clip.top, 13135 left: animation.clip.left, 13136 top: animation.clip.top 13137 }; 13138 }, 13139 13140 // Injects recently queued functions to be first in line (after "inprogress") 13141 unshift: function( element, queueLength, count ) { 13142 var queue = element.queue(); 13143 13144 if ( queueLength > 1 ) { 13145 queue.splice.apply( queue, 13146 [ 1, 0 ].concat( queue.splice( queueLength, count ) ) ); 13147 } 13148 element.dequeue(); 13149 }, 13150 13151 saveStyle: function( element ) { 13152 element.data( dataSpaceStyle, element[ 0 ].style.cssText ); 13153 }, 13154 13155 restoreStyle: function( element ) { 13156 element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || ""; 13157 element.removeData( dataSpaceStyle ); 13158 }, 13159 13160 mode: function( element, mode ) { 13161 var hidden = element.is( ":hidden" ); 13162 13163 if ( mode === "toggle" ) { 13164 mode = hidden ? "show" : "hide"; 13165 } 13166 if ( hidden ? mode === "hide" : mode === "show" ) { 13167 mode = "none"; 13168 } 13169 return mode; 13170 }, 13171 13172 // Translates a [top,left] array into a baseline value 13173 getBaseline: function( origin, original ) { 13174 var y, x; 13175 13176 switch ( origin[ 0 ] ) { 13177 case "top": 13178 y = 0; 13179 break; 13180 case "middle": 13181 y = 0.5; 13182 break; 13183 case "bottom": 13184 y = 1; 13185 break; 13186 default: 13187 y = origin[ 0 ] / original.height; 13188 } 13189 13190 switch ( origin[ 1 ] ) { 13191 case "left": 13192 x = 0; 13193 break; 13194 case "center": 13195 x = 0.5; 13196 break; 13197 case "right": 13198 x = 1; 13199 break; 13200 default: 13201 x = origin[ 1 ] / original.width; 13202 } 13203 13204 return { 13205 x: x, 13206 y: y 13207 }; 13208 }, 13209 13210 // Creates a placeholder element so that the original element can be made absolute 13211 createPlaceholder: function( element ) { 13212 var placeholder, 13213 cssPosition = element.css( "position" ), 13214 position = element.position(); 13215 13216 // Lock in margins first to account for form elements, which 13217 // will change margin if you explicitly set height 13218 // see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380 13219 // Support: Safari 13220 element.css( { 13221 marginTop: element.css( "marginTop" ), 13222 marginBottom: element.css( "marginBottom" ), 13223 marginLeft: element.css( "marginLeft" ), 13224 marginRight: element.css( "marginRight" ) 13225 } ) 13226 .outerWidth( element.outerWidth() ) 13227 .outerHeight( element.outerHeight() ); 13228 13229 if ( /^(static|relative)/.test( cssPosition ) ) { 13230 cssPosition = "absolute"; 13231 13232 placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( { 13233 13234 // Convert inline to inline block to account for inline elements 13235 // that turn to inline block based on content (like img) 13236 display: /^(inline|ruby)/.test( element.css( "display" ) ) ? 13237 "inline-block" : 13238 "block", 13239 visibility: "hidden", 13240 13241 // Margins need to be set to account for margin collapse 13242 marginTop: element.css( "marginTop" ), 13243 marginBottom: element.css( "marginBottom" ), 13244 marginLeft: element.css( "marginLeft" ), 13245 marginRight: element.css( "marginRight" ), 13246 "float": element.css( "float" ) 13247 } ) 13248 .outerWidth( element.outerWidth() ) 13249 .outerHeight( element.outerHeight() ) 13250 .addClass( "ui-effects-placeholder" ); 13251 13252 element.data( dataSpace + "placeholder", placeholder ); 13253 } 13254 13255 element.css( { 13256 position: cssPosition, 13257 left: position.left, 13258 top: position.top 13259 } ); 13260 13261 return placeholder; 13262 }, 13263 13264 removePlaceholder: function( element ) { 13265 var dataKey = dataSpace + "placeholder", 13266 placeholder = element.data( dataKey ); 13267 13268 if ( placeholder ) { 13269 placeholder.remove(); 13270 element.removeData( dataKey ); 13271 } 13272 }, 13273 13274 // Removes a placeholder if it exists and restores 13275 // properties that were modified during placeholder creation 13276 cleanUp: function( element ) { 13277 $.effects.restoreStyle( element ); 13278 $.effects.removePlaceholder( element ); 13279 }, 13280 13281 setTransition: function( element, list, factor, value ) { 13282 value = value || {}; 13283 $.each( list, function( i, x ) { 13284 var unit = element.cssUnit( x ); 13285 if ( unit[ 0 ] > 0 ) { 13286 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; 13287 } 13288 } ); 13289 return value; 13290 } 13291} ); 13292 13293// Return an effect options object for the given parameters: 13294function _normalizeArguments( effect, options, speed, callback ) { 13295 13296 // Allow passing all options as the first parameter 13297 if ( $.isPlainObject( effect ) ) { 13298 options = effect; 13299 effect = effect.effect; 13300 } 13301 13302 // Convert to an object 13303 effect = { effect: effect }; 13304 13305 // Catch (effect, null, ...) 13306 if ( options == null ) { 13307 options = {}; 13308 } 13309 13310 // Catch (effect, callback) 13311 if ( typeof options === "function" ) { 13312 callback = options; 13313 speed = null; 13314 options = {}; 13315 } 13316 13317 // Catch (effect, speed, ?) 13318 if ( typeof options === "number" || $.fx.speeds[ options ] ) { 13319 callback = speed; 13320 speed = options; 13321 options = {}; 13322 } 13323 13324 // Catch (effect, options, callback) 13325 if ( typeof speed === "function" ) { 13326 callback = speed; 13327 speed = null; 13328 } 13329 13330 // Add options to effect 13331 if ( options ) { 13332 $.extend( effect, options ); 13333 } 13334 13335 speed = speed || options.duration; 13336 effect.duration = $.fx.off ? 0 : 13337 typeof speed === "number" ? speed : 13338 speed in $.fx.speeds ? $.fx.speeds[ speed ] : 13339 $.fx.speeds._default; 13340 13341 effect.complete = callback || options.complete; 13342 13343 return effect; 13344} 13345 13346function standardAnimationOption( option ) { 13347 13348 // Valid standard speeds (nothing, number, named speed) 13349 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { 13350 return true; 13351 } 13352 13353 // Invalid strings - treat as "normal" speed 13354 if ( typeof option === "string" && !$.effects.effect[ option ] ) { 13355 return true; 13356 } 13357 13358 // Complete callback 13359 if ( typeof option === "function" ) { 13360 return true; 13361 } 13362 13363 // Options hash (but not naming an effect) 13364 if ( typeof option === "object" && !option.effect ) { 13365 return true; 13366 } 13367 13368 // Didn't match any standard API 13369 return false; 13370} 13371 13372$.fn.extend( { 13373 effect: function( /* effect, options, speed, callback */ ) { 13374 var args = _normalizeArguments.apply( this, arguments ), 13375 effectMethod = $.effects.effect[ args.effect ], 13376 defaultMode = effectMethod.mode, 13377 queue = args.queue, 13378 queueName = queue || "fx", 13379 complete = args.complete, 13380 mode = args.mode, 13381 modes = [], 13382 prefilter = function( next ) { 13383 var el = $( this ), 13384 normalizedMode = $.effects.mode( el, mode ) || defaultMode; 13385 13386 // Sentinel for duck-punching the :animated pseudo-selector 13387 el.data( dataSpaceAnimated, true ); 13388 13389 // Save effect mode for later use, 13390 // we can't just call $.effects.mode again later, 13391 // as the .show() below destroys the initial state 13392 modes.push( normalizedMode ); 13393 13394 // See $.uiBackCompat inside of run() for removal of defaultMode in 1.14 13395 if ( defaultMode && ( normalizedMode === "show" || 13396 ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) { 13397 el.show(); 13398 } 13399 13400 if ( !defaultMode || normalizedMode !== "none" ) { 13401 $.effects.saveStyle( el ); 13402 } 13403 13404 if ( typeof next === "function" ) { 13405 next(); 13406 } 13407 }; 13408 13409 if ( $.fx.off || !effectMethod ) { 13410 13411 // Delegate to the original method (e.g., .show()) if possible 13412 if ( mode ) { 13413 return this[ mode ]( args.duration, complete ); 13414 } else { 13415 return this.each( function() { 13416 if ( complete ) { 13417 complete.call( this ); 13418 } 13419 } ); 13420 } 13421 } 13422 13423 function run( next ) { 13424 var elem = $( this ); 13425 13426 function cleanup() { 13427 elem.removeData( dataSpaceAnimated ); 13428 13429 $.effects.cleanUp( elem ); 13430 13431 if ( args.mode === "hide" ) { 13432 elem.hide(); 13433 } 13434 13435 done(); 13436 } 13437 13438 function done() { 13439 if ( typeof complete === "function" ) { 13440 complete.call( elem[ 0 ] ); 13441 } 13442 13443 if ( typeof next === "function" ) { 13444 next(); 13445 } 13446 } 13447 13448 // Override mode option on a per element basis, 13449 // as toggle can be either show or hide depending on element state 13450 args.mode = modes.shift(); 13451 13452 if ( $.uiBackCompat === true && !defaultMode ) { 13453 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { 13454 13455 // Call the core method to track "olddisplay" properly 13456 elem[ mode ](); 13457 done(); 13458 } else { 13459 effectMethod.call( elem[ 0 ], args, done ); 13460 } 13461 } else { 13462 if ( args.mode === "none" ) { 13463 13464 // Call the core method to track "olddisplay" properly 13465 elem[ mode ](); 13466 done(); 13467 } else { 13468 effectMethod.call( elem[ 0 ], args, cleanup ); 13469 } 13470 } 13471 } 13472 13473 // Run prefilter on all elements first to ensure that 13474 // any showing or hiding happens before placeholder creation, 13475 // which ensures that any layout changes are correctly captured. 13476 return queue === false ? 13477 this.each( prefilter ).each( run ) : 13478 this.queue( queueName, prefilter ).queue( queueName, run ); 13479 }, 13480 13481 show: ( function( orig ) { 13482 return function( option ) { 13483 if ( standardAnimationOption( option ) ) { 13484 return orig.apply( this, arguments ); 13485 } else { 13486 var args = _normalizeArguments.apply( this, arguments ); 13487 args.mode = "show"; 13488 return this.effect.call( this, args ); 13489 } 13490 }; 13491 } )( $.fn.show ), 13492 13493 hide: ( function( orig ) { 13494 return function( option ) { 13495 if ( standardAnimationOption( option ) ) { 13496 return orig.apply( this, arguments ); 13497 } else { 13498 var args = _normalizeArguments.apply( this, arguments ); 13499 args.mode = "hide"; 13500 return this.effect.call( this, args ); 13501 } 13502 }; 13503 } )( $.fn.hide ), 13504 13505 toggle: ( function( orig ) { 13506 return function( option ) { 13507 if ( standardAnimationOption( option ) || typeof option === "boolean" ) { 13508 return orig.apply( this, arguments ); 13509 } else { 13510 var args = _normalizeArguments.apply( this, arguments ); 13511 args.mode = "toggle"; 13512 return this.effect.call( this, args ); 13513 } 13514 }; 13515 } )( $.fn.toggle ), 13516 13517 cssUnit: function( key ) { 13518 var style = this.css( key ), 13519 val = []; 13520 13521 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { 13522 if ( style.indexOf( unit ) > 0 ) { 13523 val = [ parseFloat( style ), unit ]; 13524 } 13525 } ); 13526 return val; 13527 }, 13528 13529 cssClip: function( clipObj ) { 13530 if ( clipObj ) { 13531 return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " + 13532 clipObj.bottom + "px " + clipObj.left + "px)" ); 13533 } 13534 return parseClip( this.css( "clip" ), this ); 13535 }, 13536 13537 transfer: function( options, done ) { 13538 var element = $( this ), 13539 target = $( options.to ), 13540 targetFixed = target.css( "position" ) === "fixed", 13541 body = $( "body" ), 13542 fixTop = targetFixed ? body.scrollTop() : 0, 13543 fixLeft = targetFixed ? body.scrollLeft() : 0, 13544 endPosition = target.offset(), 13545 animation = { 13546 top: endPosition.top - fixTop, 13547 left: endPosition.left - fixLeft, 13548 height: target.innerHeight(), 13549 width: target.innerWidth() 13550 }, 13551 startPosition = element.offset(), 13552 transfer = $( "<div class='ui-effects-transfer'></div>" ); 13553 13554 transfer 13555 .appendTo( "body" ) 13556 .addClass( options.className ) 13557 .css( { 13558 top: startPosition.top - fixTop, 13559 left: startPosition.left - fixLeft, 13560 height: element.innerHeight(), 13561 width: element.innerWidth(), 13562 position: targetFixed ? "fixed" : "absolute" 13563 } ) 13564 .animate( animation, options.duration, options.easing, function() { 13565 transfer.remove(); 13566 if ( typeof done === "function" ) { 13567 done(); 13568 } 13569 } ); 13570 } 13571} ); 13572 13573function parseClip( str, element ) { 13574 var outerWidth = element.outerWidth(), 13575 outerHeight = element.outerHeight(), 13576 clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/, 13577 values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ]; 13578 13579 return { 13580 top: parseFloat( values[ 1 ] ) || 0, 13581 right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ), 13582 bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ), 13583 left: parseFloat( values[ 4 ] ) || 0 13584 }; 13585} 13586 13587$.fx.step.clip = function( fx ) { 13588 if ( !fx.clipInit ) { 13589 fx.start = $( fx.elem ).cssClip(); 13590 if ( typeof fx.end === "string" ) { 13591 fx.end = parseClip( fx.end, fx.elem ); 13592 } 13593 fx.clipInit = true; 13594 } 13595 13596 $( fx.elem ).cssClip( { 13597 top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top, 13598 right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right, 13599 bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom, 13600 left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left 13601 } ); 13602}; 13603 13604} )(); 13605 13606/******************************************************************************/ 13607/*********************************** EASING ***********************************/ 13608/******************************************************************************/ 13609 13610( function() { 13611 13612// Based on easing equations from Robert Penner (http://robertpenner.com/easing) 13613 13614var baseEasings = {}; 13615 13616$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { 13617 baseEasings[ name ] = function( p ) { 13618 return Math.pow( p, i + 2 ); 13619 }; 13620} ); 13621 13622$.extend( baseEasings, { 13623 Sine: function( p ) { 13624 return 1 - Math.cos( p * Math.PI / 2 ); 13625 }, 13626 Circ: function( p ) { 13627 return 1 - Math.sqrt( 1 - p * p ); 13628 }, 13629 Elastic: function( p ) { 13630 return p === 0 || p === 1 ? p : 13631 -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 ); 13632 }, 13633 Back: function( p ) { 13634 return p * p * ( 3 * p - 2 ); 13635 }, 13636 Bounce: function( p ) { 13637 var pow2, 13638 bounce = 4; 13639 13640 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} 13641 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); 13642 } 13643} ); 13644 13645$.each( baseEasings, function( name, easeIn ) { 13646 $.easing[ "easeIn" + name ] = easeIn; 13647 $.easing[ "easeOut" + name ] = function( p ) { 13648 return 1 - easeIn( 1 - p ); 13649 }; 13650 $.easing[ "easeInOut" + name ] = function( p ) { 13651 return p < 0.5 ? 13652 easeIn( p * 2 ) / 2 : 13653 1 - easeIn( p * -2 + 2 ) / 2; 13654 }; 13655} ); 13656 13657} )(); 13658 13659var effect = $.effects; 13660 13661 13662/*! 13663 * jQuery UI Effects Blind 1.14.1 13664 * https://jqueryui.com 13665 * 13666 * Copyright OpenJS Foundation and other contributors 13667 * Released under the MIT license. 13668 * https://jquery.org/license 13669 */ 13670 13671//>>label: Blind Effect 13672//>>group: Effects 13673//>>description: Blinds the element. 13674//>>docs: https://api.jqueryui.com/blind-effect/ 13675//>>demos: https://jqueryui.com/effect/ 13676 13677 13678var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) { 13679 var map = { 13680 up: [ "bottom", "top" ], 13681 vertical: [ "bottom", "top" ], 13682 down: [ "top", "bottom" ], 13683 left: [ "right", "left" ], 13684 horizontal: [ "right", "left" ], 13685 right: [ "left", "right" ] 13686 }, 13687 element = $( this ), 13688 direction = options.direction || "up", 13689 start = element.cssClip(), 13690 animate = { clip: $.extend( {}, start ) }, 13691 placeholder = $.effects.createPlaceholder( element ); 13692 13693 animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ]; 13694 13695 if ( options.mode === "show" ) { 13696 element.cssClip( animate.clip ); 13697 if ( placeholder ) { 13698 placeholder.css( $.effects.clipToBox( animate ) ); 13699 } 13700 13701 animate.clip = start; 13702 } 13703 13704 if ( placeholder ) { 13705 placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing ); 13706 } 13707 13708 element.animate( animate, { 13709 queue: false, 13710 duration: options.duration, 13711 easing: options.easing, 13712 complete: done 13713 } ); 13714} ); 13715 13716 13717/*! 13718 * jQuery UI Effects Bounce 1.14.1 13719 * https://jqueryui.com 13720 * 13721 * Copyright OpenJS Foundation and other contributors 13722 * Released under the MIT license. 13723 * https://jquery.org/license 13724 */ 13725 13726//>>label: Bounce Effect 13727//>>group: Effects 13728//>>description: Bounces an element horizontally or vertically n times. 13729//>>docs: https://api.jqueryui.com/bounce-effect/ 13730//>>demos: https://jqueryui.com/effect/ 13731 13732 13733var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) { 13734 var upAnim, downAnim, refValue, 13735 element = $( this ), 13736 13737 // Defaults: 13738 mode = options.mode, 13739 hide = mode === "hide", 13740 show = mode === "show", 13741 direction = options.direction || "up", 13742 distance = options.distance, 13743 times = options.times || 5, 13744 13745 // Number of internal animations 13746 anims = times * 2 + ( show || hide ? 1 : 0 ), 13747 speed = options.duration / anims, 13748 easing = options.easing, 13749 13750 // Utility: 13751 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 13752 motion = ( direction === "up" || direction === "left" ), 13753 i = 0, 13754 13755 queuelen = element.queue().length; 13756 13757 $.effects.createPlaceholder( element ); 13758 13759 refValue = element.css( ref ); 13760 13761 // Default distance for the BIGGEST bounce is the outer Distance / 3 13762 if ( !distance ) { 13763 distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; 13764 } 13765 13766 if ( show ) { 13767 downAnim = { opacity: 1 }; 13768 downAnim[ ref ] = refValue; 13769 13770 // If we are showing, force opacity 0 and set the initial position 13771 // then do the "first" animation 13772 element 13773 .css( "opacity", 0 ) 13774 .css( ref, motion ? -distance * 2 : distance * 2 ) 13775 .animate( downAnim, speed, easing ); 13776 } 13777 13778 // Start at the smallest distance if we are hiding 13779 if ( hide ) { 13780 distance = distance / Math.pow( 2, times - 1 ); 13781 } 13782 13783 downAnim = {}; 13784 downAnim[ ref ] = refValue; 13785 13786 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here 13787 for ( ; i < times; i++ ) { 13788 upAnim = {}; 13789 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 13790 13791 element 13792 .animate( upAnim, speed, easing ) 13793 .animate( downAnim, speed, easing ); 13794 13795 distance = hide ? distance * 2 : distance / 2; 13796 } 13797 13798 // Last Bounce when Hiding 13799 if ( hide ) { 13800 upAnim = { opacity: 0 }; 13801 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 13802 13803 element.animate( upAnim, speed, easing ); 13804 } 13805 13806 element.queue( done ); 13807 13808 $.effects.unshift( element, queuelen, anims + 1 ); 13809} ); 13810 13811 13812/*! 13813 * jQuery UI Effects Clip 1.14.1 13814 * https://jqueryui.com 13815 * 13816 * Copyright OpenJS Foundation and other contributors 13817 * Released under the MIT license. 13818 * https://jquery.org/license 13819 */ 13820 13821//>>label: Clip Effect 13822//>>group: Effects 13823//>>description: Clips the element on and off like an old TV. 13824//>>docs: https://api.jqueryui.com/clip-effect/ 13825//>>demos: https://jqueryui.com/effect/ 13826 13827 13828var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) { 13829 var start, 13830 animate = {}, 13831 element = $( this ), 13832 direction = options.direction || "vertical", 13833 both = direction === "both", 13834 horizontal = both || direction === "horizontal", 13835 vertical = both || direction === "vertical"; 13836 13837 start = element.cssClip(); 13838 animate.clip = { 13839 top: vertical ? ( start.bottom - start.top ) / 2 : start.top, 13840 right: horizontal ? ( start.right - start.left ) / 2 : start.right, 13841 bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom, 13842 left: horizontal ? ( start.right - start.left ) / 2 : start.left 13843 }; 13844 13845 $.effects.createPlaceholder( element ); 13846 13847 if ( options.mode === "show" ) { 13848 element.cssClip( animate.clip ); 13849 animate.clip = start; 13850 } 13851 13852 element.animate( animate, { 13853 queue: false, 13854 duration: options.duration, 13855 easing: options.easing, 13856 complete: done 13857 } ); 13858 13859} ); 13860 13861 13862/*! 13863 * jQuery UI Effects Drop 1.14.1 13864 * https://jqueryui.com 13865 * 13866 * Copyright OpenJS Foundation and other contributors 13867 * Released under the MIT license. 13868 * https://jquery.org/license 13869 */ 13870 13871//>>label: Drop Effect 13872//>>group: Effects 13873//>>description: Moves an element in one direction and hides it at the same time. 13874//>>docs: https://api.jqueryui.com/drop-effect/ 13875//>>demos: https://jqueryui.com/effect/ 13876 13877 13878var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) { 13879 13880 var distance, 13881 element = $( this ), 13882 mode = options.mode, 13883 show = mode === "show", 13884 direction = options.direction || "left", 13885 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 13886 motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=", 13887 oppositeMotion = ( motion === "+=" ) ? "-=" : "+=", 13888 animation = { 13889 opacity: 0 13890 }; 13891 13892 $.effects.createPlaceholder( element ); 13893 13894 distance = options.distance || 13895 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2; 13896 13897 animation[ ref ] = motion + distance; 13898 13899 if ( show ) { 13900 element.css( animation ); 13901 13902 animation[ ref ] = oppositeMotion + distance; 13903 animation.opacity = 1; 13904 } 13905 13906 // Animate 13907 element.animate( animation, { 13908 queue: false, 13909 duration: options.duration, 13910 easing: options.easing, 13911 complete: done 13912 } ); 13913} ); 13914 13915 13916/*! 13917 * jQuery UI Effects Explode 1.14.1 13918 * https://jqueryui.com 13919 * 13920 * Copyright OpenJS Foundation and other contributors 13921 * Released under the MIT license. 13922 * https://jquery.org/license 13923 */ 13924 13925//>>label: Explode Effect 13926//>>group: Effects 13927/* eslint-disable max-len */ 13928//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness. 13929/* eslint-enable max-len */ 13930//>>docs: https://api.jqueryui.com/explode-effect/ 13931//>>demos: https://jqueryui.com/effect/ 13932 13933 13934var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) { 13935 13936 var i, j, left, top, mx, my, 13937 rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3, 13938 cells = rows, 13939 element = $( this ), 13940 mode = options.mode, 13941 show = mode === "show", 13942 13943 // Show and then visibility:hidden the element before calculating offset 13944 offset = element.show().css( "visibility", "hidden" ).offset(), 13945 13946 // Width and height of a piece 13947 width = Math.ceil( element.outerWidth() / cells ), 13948 height = Math.ceil( element.outerHeight() / rows ), 13949 pieces = []; 13950 13951 // Children animate complete: 13952 function childComplete() { 13953 pieces.push( this ); 13954 if ( pieces.length === rows * cells ) { 13955 animComplete(); 13956 } 13957 } 13958 13959 // Clone the element for each row and cell. 13960 for ( i = 0; i < rows; i++ ) { // ===> 13961 top = offset.top + i * height; 13962 my = i - ( rows - 1 ) / 2; 13963 13964 for ( j = 0; j < cells; j++ ) { // ||| 13965 left = offset.left + j * width; 13966 mx = j - ( cells - 1 ) / 2; 13967 13968 // Create a clone of the now hidden main element that will be absolute positioned 13969 // within a wrapper div off the -left and -top equal to size of our pieces 13970 element 13971 .clone() 13972 .appendTo( "body" ) 13973 .wrap( "<div></div>" ) 13974 .css( { 13975 position: "absolute", 13976 visibility: "visible", 13977 left: -j * width, 13978 top: -i * height 13979 } ) 13980 13981 // Select the wrapper - make it overflow: hidden and absolute positioned based on 13982 // where the original was located +left and +top equal to the size of pieces 13983 .parent() 13984 .addClass( "ui-effects-explode" ) 13985 .css( { 13986 position: "absolute", 13987 overflow: "hidden", 13988 width: width, 13989 height: height, 13990 left: left + ( show ? mx * width : 0 ), 13991 top: top + ( show ? my * height : 0 ), 13992 opacity: show ? 0 : 1 13993 } ) 13994 .animate( { 13995 left: left + ( show ? 0 : mx * width ), 13996 top: top + ( show ? 0 : my * height ), 13997 opacity: show ? 1 : 0 13998 }, options.duration || 500, options.easing, childComplete ); 13999 } 14000 } 14001 14002 function animComplete() { 14003 element.css( { 14004 visibility: "visible" 14005 } ); 14006 $( pieces ).remove(); 14007 done(); 14008 } 14009} ); 14010 14011 14012/*! 14013 * jQuery UI Effects Fade 1.14.1 14014 * https://jqueryui.com 14015 * 14016 * Copyright OpenJS Foundation and other contributors 14017 * Released under the MIT license. 14018 * https://jquery.org/license 14019 */ 14020 14021//>>label: Fade Effect 14022//>>group: Effects 14023//>>description: Fades the element. 14024//>>docs: https://api.jqueryui.com/fade-effect/ 14025//>>demos: https://jqueryui.com/effect/ 14026 14027 14028var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) { 14029 var show = options.mode === "show"; 14030 14031 $( this ) 14032 .css( "opacity", show ? 0 : 1 ) 14033 .animate( { 14034 opacity: show ? 1 : 0 14035 }, { 14036 queue: false, 14037 duration: options.duration, 14038 easing: options.easing, 14039 complete: done 14040 } ); 14041} ); 14042 14043 14044/*! 14045 * jQuery UI Effects Fold 1.14.1 14046 * https://jqueryui.com 14047 * 14048 * Copyright OpenJS Foundation and other contributors 14049 * Released under the MIT license. 14050 * https://jquery.org/license 14051 */ 14052 14053//>>label: Fold Effect 14054//>>group: Effects 14055//>>description: Folds an element first horizontally and then vertically. 14056//>>docs: https://api.jqueryui.com/fold-effect/ 14057//>>demos: https://jqueryui.com/effect/ 14058 14059 14060var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) { 14061 14062 // Create element 14063 var element = $( this ), 14064 mode = options.mode, 14065 show = mode === "show", 14066 hide = mode === "hide", 14067 size = options.size || 15, 14068 percent = /([0-9]+)%/.exec( size ), 14069 horizFirst = !!options.horizFirst, 14070 ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ], 14071 duration = options.duration / 2, 14072 14073 placeholder = $.effects.createPlaceholder( element ), 14074 14075 start = element.cssClip(), 14076 animation1 = { clip: $.extend( {}, start ) }, 14077 animation2 = { clip: $.extend( {}, start ) }, 14078 14079 distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ], 14080 14081 queuelen = element.queue().length; 14082 14083 if ( percent ) { 14084 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; 14085 } 14086 animation1.clip[ ref[ 0 ] ] = size; 14087 animation2.clip[ ref[ 0 ] ] = size; 14088 animation2.clip[ ref[ 1 ] ] = 0; 14089 14090 if ( show ) { 14091 element.cssClip( animation2.clip ); 14092 if ( placeholder ) { 14093 placeholder.css( $.effects.clipToBox( animation2 ) ); 14094 } 14095 14096 animation2.clip = start; 14097 } 14098 14099 // Animate 14100 element 14101 .queue( function( next ) { 14102 if ( placeholder ) { 14103 placeholder 14104 .animate( $.effects.clipToBox( animation1 ), duration, options.easing ) 14105 .animate( $.effects.clipToBox( animation2 ), duration, options.easing ); 14106 } 14107 14108 next(); 14109 } ) 14110 .animate( animation1, duration, options.easing ) 14111 .animate( animation2, duration, options.easing ) 14112 .queue( done ); 14113 14114 $.effects.unshift( element, queuelen, 4 ); 14115} ); 14116 14117 14118/*! 14119 * jQuery UI Effects Highlight 1.14.1 14120 * https://jqueryui.com 14121 * 14122 * Copyright OpenJS Foundation and other contributors 14123 * Released under the MIT license. 14124 * https://jquery.org/license 14125 */ 14126 14127//>>label: Highlight Effect 14128//>>group: Effects 14129//>>description: Highlights the background of an element in a defined color for a custom duration. 14130//>>docs: https://api.jqueryui.com/highlight-effect/ 14131//>>demos: https://jqueryui.com/effect/ 14132 14133 14134var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) { 14135 var element = $( this ), 14136 animation = { 14137 backgroundColor: element.css( "backgroundColor" ) 14138 }; 14139 14140 if ( options.mode === "hide" ) { 14141 animation.opacity = 0; 14142 } 14143 14144 $.effects.saveStyle( element ); 14145 14146 element 14147 .css( { 14148 backgroundImage: "none", 14149 backgroundColor: options.color || "#ffff99" 14150 } ) 14151 .animate( animation, { 14152 queue: false, 14153 duration: options.duration, 14154 easing: options.easing, 14155 complete: done 14156 } ); 14157} ); 14158 14159 14160/*! 14161 * jQuery UI Effects Size 1.14.1 14162 * https://jqueryui.com 14163 * 14164 * Copyright OpenJS Foundation and other contributors 14165 * Released under the MIT license. 14166 * https://jquery.org/license 14167 */ 14168 14169//>>label: Size Effect 14170//>>group: Effects 14171//>>description: Resize an element to a specified width and height. 14172//>>docs: https://api.jqueryui.com/size-effect/ 14173//>>demos: https://jqueryui.com/effect/ 14174 14175 14176var effectsEffectSize = $.effects.define( "size", function( options, done ) { 14177 14178 // Create element 14179 var baseline, factor, temp, 14180 element = $( this ), 14181 14182 // Copy for children 14183 cProps = [ "fontSize" ], 14184 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], 14185 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], 14186 14187 // Set options 14188 mode = options.mode, 14189 restore = mode !== "effect", 14190 scale = options.scale || "both", 14191 origin = options.origin || [ "middle", "center" ], 14192 position = element.css( "position" ), 14193 pos = element.position(), 14194 original = $.effects.scaledDimensions( element ), 14195 from = options.from || original, 14196 to = options.to || $.effects.scaledDimensions( element, 0 ); 14197 14198 $.effects.createPlaceholder( element ); 14199 14200 if ( mode === "show" ) { 14201 temp = from; 14202 from = to; 14203 to = temp; 14204 } 14205 14206 // Set scaling factor 14207 factor = { 14208 from: { 14209 y: from.height / original.height, 14210 x: from.width / original.width 14211 }, 14212 to: { 14213 y: to.height / original.height, 14214 x: to.width / original.width 14215 } 14216 }; 14217 14218 // Scale the css box 14219 if ( scale === "box" || scale === "both" ) { 14220 14221 // Vertical props scaling 14222 if ( factor.from.y !== factor.to.y ) { 14223 from = $.effects.setTransition( element, vProps, factor.from.y, from ); 14224 to = $.effects.setTransition( element, vProps, factor.to.y, to ); 14225 } 14226 14227 // Horizontal props scaling 14228 if ( factor.from.x !== factor.to.x ) { 14229 from = $.effects.setTransition( element, hProps, factor.from.x, from ); 14230 to = $.effects.setTransition( element, hProps, factor.to.x, to ); 14231 } 14232 } 14233 14234 // Scale the content 14235 if ( scale === "content" || scale === "both" ) { 14236 14237 // Vertical props scaling 14238 if ( factor.from.y !== factor.to.y ) { 14239 from = $.effects.setTransition( element, cProps, factor.from.y, from ); 14240 to = $.effects.setTransition( element, cProps, factor.to.y, to ); 14241 } 14242 } 14243 14244 // Adjust the position properties based on the provided origin points 14245 if ( origin ) { 14246 baseline = $.effects.getBaseline( origin, original ); 14247 from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top; 14248 from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left; 14249 to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top; 14250 to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left; 14251 } 14252 delete from.outerHeight; 14253 delete from.outerWidth; 14254 element.css( from ); 14255 14256 // Animate the children if desired 14257 if ( scale === "content" || scale === "both" ) { 14258 14259 vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps ); 14260 hProps = hProps.concat( [ "marginLeft", "marginRight" ] ); 14261 14262 // Only animate children with width attributes specified 14263 // TODO: is this right? should we include anything with css width specified as well 14264 element.find( "*[width]" ).each( function() { 14265 var child = $( this ), 14266 childOriginal = $.effects.scaledDimensions( child ), 14267 childFrom = { 14268 height: childOriginal.height * factor.from.y, 14269 width: childOriginal.width * factor.from.x, 14270 outerHeight: childOriginal.outerHeight * factor.from.y, 14271 outerWidth: childOriginal.outerWidth * factor.from.x 14272 }, 14273 childTo = { 14274 height: childOriginal.height * factor.to.y, 14275 width: childOriginal.width * factor.to.x, 14276 outerHeight: childOriginal.height * factor.to.y, 14277 outerWidth: childOriginal.width * factor.to.x 14278 }; 14279 14280 // Vertical props scaling 14281 if ( factor.from.y !== factor.to.y ) { 14282 childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom ); 14283 childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo ); 14284 } 14285 14286 // Horizontal props scaling 14287 if ( factor.from.x !== factor.to.x ) { 14288 childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom ); 14289 childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo ); 14290 } 14291 14292 if ( restore ) { 14293 $.effects.saveStyle( child ); 14294 } 14295 14296 // Animate children 14297 child.css( childFrom ); 14298 child.animate( childTo, options.duration, options.easing, function() { 14299 14300 // Restore children 14301 if ( restore ) { 14302 $.effects.restoreStyle( child ); 14303 } 14304 } ); 14305 } ); 14306 } 14307 14308 // Animate 14309 element.animate( to, { 14310 queue: false, 14311 duration: options.duration, 14312 easing: options.easing, 14313 complete: function() { 14314 14315 var offset = element.offset(); 14316 14317 if ( to.opacity === 0 ) { 14318 element.css( "opacity", from.opacity ); 14319 } 14320 14321 if ( !restore ) { 14322 element 14323 .css( "position", position === "static" ? "relative" : position ) 14324 .offset( offset ); 14325 14326 // Need to save style here so that automatic style restoration 14327 // doesn't restore to the original styles from before the animation. 14328 $.effects.saveStyle( element ); 14329 } 14330 14331 done(); 14332 } 14333 } ); 14334 14335} ); 14336 14337 14338/*! 14339 * jQuery UI Effects Scale 1.14.1 14340 * https://jqueryui.com 14341 * 14342 * Copyright OpenJS Foundation and other contributors 14343 * Released under the MIT license. 14344 * https://jquery.org/license 14345 */ 14346 14347//>>label: Scale Effect 14348//>>group: Effects 14349//>>description: Grows or shrinks an element and its content. 14350//>>docs: https://api.jqueryui.com/scale-effect/ 14351//>>demos: https://jqueryui.com/effect/ 14352 14353 14354var effectsEffectScale = $.effects.define( "scale", function( options, done ) { 14355 14356 // Create element 14357 var el = $( this ), 14358 mode = options.mode, 14359 percent = parseInt( options.percent, 10 ) || 14360 ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ), 14361 14362 newOptions = $.extend( true, { 14363 from: $.effects.scaledDimensions( el ), 14364 to: $.effects.scaledDimensions( el, percent, options.direction || "both" ), 14365 origin: options.origin || [ "middle", "center" ] 14366 }, options ); 14367 14368 // Fade option to support puff 14369 if ( options.fade ) { 14370 newOptions.from.opacity = 1; 14371 newOptions.to.opacity = 0; 14372 } 14373 14374 $.effects.effect.size.call( this, newOptions, done ); 14375} ); 14376 14377 14378/*! 14379 * jQuery UI Effects Puff 1.14.1 14380 * https://jqueryui.com 14381 * 14382 * Copyright OpenJS Foundation and other contributors 14383 * Released under the MIT license. 14384 * https://jquery.org/license 14385 */ 14386 14387//>>label: Puff Effect 14388//>>group: Effects 14389//>>description: Creates a puff effect by scaling the element up and hiding it at the same time. 14390//>>docs: https://api.jqueryui.com/puff-effect/ 14391//>>demos: https://jqueryui.com/effect/ 14392 14393 14394var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) { 14395 var newOptions = $.extend( true, {}, options, { 14396 fade: true, 14397 percent: parseInt( options.percent, 10 ) || 150 14398 } ); 14399 14400 $.effects.effect.scale.call( this, newOptions, done ); 14401} ); 14402 14403 14404/*! 14405 * jQuery UI Effects Pulsate 1.14.1 14406 * https://jqueryui.com 14407 * 14408 * Copyright OpenJS Foundation and other contributors 14409 * Released under the MIT license. 14410 * https://jquery.org/license 14411 */ 14412 14413//>>label: Pulsate Effect 14414//>>group: Effects 14415//>>description: Pulsates an element n times by changing the opacity to zero and back. 14416//>>docs: https://api.jqueryui.com/pulsate-effect/ 14417//>>demos: https://jqueryui.com/effect/ 14418 14419 14420var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) { 14421 var element = $( this ), 14422 mode = options.mode, 14423 show = mode === "show", 14424 hide = mode === "hide", 14425 showhide = show || hide, 14426 14427 // Showing or hiding leaves off the "last" animation 14428 anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), 14429 duration = options.duration / anims, 14430 animateTo = 0, 14431 i = 1, 14432 queuelen = element.queue().length; 14433 14434 if ( show || !element.is( ":visible" ) ) { 14435 element.css( "opacity", 0 ).show(); 14436 animateTo = 1; 14437 } 14438 14439 // Anims - 1 opacity "toggles" 14440 for ( ; i < anims; i++ ) { 14441 element.animate( { opacity: animateTo }, duration, options.easing ); 14442 animateTo = 1 - animateTo; 14443 } 14444 14445 element.animate( { opacity: animateTo }, duration, options.easing ); 14446 14447 element.queue( done ); 14448 14449 $.effects.unshift( element, queuelen, anims + 1 ); 14450} ); 14451 14452 14453/*! 14454 * jQuery UI Effects Shake 1.14.1 14455 * https://jqueryui.com 14456 * 14457 * Copyright OpenJS Foundation and other contributors 14458 * Released under the MIT license. 14459 * https://jquery.org/license 14460 */ 14461 14462//>>label: Shake Effect 14463//>>group: Effects 14464//>>description: Shakes an element horizontally or vertically n times. 14465//>>docs: https://api.jqueryui.com/shake-effect/ 14466//>>demos: https://jqueryui.com/effect/ 14467 14468 14469var effectsEffectShake = $.effects.define( "shake", function( options, done ) { 14470 14471 var i = 1, 14472 element = $( this ), 14473 direction = options.direction || "left", 14474 distance = options.distance || 20, 14475 times = options.times || 3, 14476 anims = times * 2 + 1, 14477 speed = Math.round( options.duration / anims ), 14478 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 14479 positiveMotion = ( direction === "up" || direction === "left" ), 14480 animation = {}, 14481 animation1 = {}, 14482 animation2 = {}, 14483 14484 queuelen = element.queue().length; 14485 14486 $.effects.createPlaceholder( element ); 14487 14488 // Animation 14489 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; 14490 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; 14491 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; 14492 14493 // Animate 14494 element.animate( animation, speed, options.easing ); 14495 14496 // Shakes 14497 for ( ; i < times; i++ ) { 14498 element 14499 .animate( animation1, speed, options.easing ) 14500 .animate( animation2, speed, options.easing ); 14501 } 14502 14503 element 14504 .animate( animation1, speed, options.easing ) 14505 .animate( animation, speed / 2, options.easing ) 14506 .queue( done ); 14507 14508 $.effects.unshift( element, queuelen, anims + 1 ); 14509} ); 14510 14511 14512/*! 14513 * jQuery UI Effects Slide 1.14.1 14514 * https://jqueryui.com 14515 * 14516 * Copyright OpenJS Foundation and other contributors 14517 * Released under the MIT license. 14518 * https://jquery.org/license 14519 */ 14520 14521//>>label: Slide Effect 14522//>>group: Effects 14523//>>description: Slides an element in and out of the viewport. 14524//>>docs: https://api.jqueryui.com/slide-effect/ 14525//>>demos: https://jqueryui.com/effect/ 14526 14527 14528var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) { 14529 var startClip, startRef, 14530 element = $( this ), 14531 map = { 14532 up: [ "bottom", "top" ], 14533 down: [ "top", "bottom" ], 14534 left: [ "right", "left" ], 14535 right: [ "left", "right" ] 14536 }, 14537 mode = options.mode, 14538 direction = options.direction || "left", 14539 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 14540 positiveMotion = ( direction === "up" || direction === "left" ), 14541 distance = options.distance || 14542 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ), 14543 animation = {}; 14544 14545 $.effects.createPlaceholder( element ); 14546 14547 startClip = element.cssClip(); 14548 startRef = element.position()[ ref ]; 14549 14550 // Define hide animation 14551 animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef; 14552 animation.clip = element.cssClip(); 14553 animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ]; 14554 14555 // Reverse the animation if we're showing 14556 if ( mode === "show" ) { 14557 element.cssClip( animation.clip ); 14558 element.css( ref, animation[ ref ] ); 14559 animation.clip = startClip; 14560 animation[ ref ] = startRef; 14561 } 14562 14563 // Actually animate 14564 element.animate( animation, { 14565 queue: false, 14566 duration: options.duration, 14567 easing: options.easing, 14568 complete: done 14569 } ); 14570} ); 14571 14572 14573/*! 14574 * jQuery UI Effects Transfer 1.14.1 14575 * https://jqueryui.com 14576 * 14577 * Copyright OpenJS Foundation and other contributors 14578 * Released under the MIT license. 14579 * https://jquery.org/license 14580 */ 14581 14582//>>label: Transfer Effect 14583//>>group: Effects 14584//>>description: Displays a transfer effect from one element to another. 14585//>>docs: https://api.jqueryui.com/transfer-effect/ 14586//>>demos: https://jqueryui.com/effect/ 14587 14588 14589var effect; 14590if ( $.uiBackCompat === true ) { 14591 effect = $.effects.define( "transfer", function( options, done ) { 14592 $( this ).transfer( options, done ); 14593 } ); 14594} 14595var effectsEffectTransfer = effect; 14596 14597 14598/*! 14599 * jQuery UI Focusable 1.14.1 14600 * https://jqueryui.com 14601 * 14602 * Copyright OpenJS Foundation and other contributors 14603 * Released under the MIT license. 14604 * https://jquery.org/license 14605 */ 14606 14607//>>label: :focusable Selector 14608//>>group: Core 14609//>>description: Selects elements which can be focused. 14610//>>docs: https://api.jqueryui.com/focusable-selector/ 14611 14612 14613// Selectors 14614$.ui.focusable = function( element, hasTabindex ) { 14615 var map, mapName, img, focusableIfVisible, fieldset, 14616 nodeName = element.nodeName.toLowerCase(); 14617 14618 if ( "area" === nodeName ) { 14619 map = element.parentNode; 14620 mapName = map.name; 14621 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 14622 return false; 14623 } 14624 img = $( "img[usemap='#" + mapName + "']" ); 14625 return img.length > 0 && img.is( ":visible" ); 14626 } 14627 14628 if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) { 14629 focusableIfVisible = !element.disabled; 14630 14631 if ( focusableIfVisible ) { 14632 14633 // Form controls within a disabled fieldset are disabled. 14634 // However, controls within the fieldset's legend do not get disabled. 14635 // Since controls generally aren't placed inside legends, we skip 14636 // this portion of the check. 14637 fieldset = $( element ).closest( "fieldset" )[ 0 ]; 14638 if ( fieldset ) { 14639 focusableIfVisible = !fieldset.disabled; 14640 } 14641 } 14642 } else if ( "a" === nodeName ) { 14643 focusableIfVisible = element.href || hasTabindex; 14644 } else { 14645 focusableIfVisible = hasTabindex; 14646 } 14647 14648 return focusableIfVisible && $( element ).is( ":visible" ) && 14649 $( element ).css( "visibility" ) === "visible"; 14650}; 14651 14652$.extend( $.expr.pseudos, { 14653 focusable: function( element ) { 14654 return $.ui.focusable( element, $.attr( element, "tabindex" ) != null ); 14655 } 14656} ); 14657 14658var focusable = $.ui.focusable; 14659 14660 14661/*! 14662 * jQuery UI Form Reset Mixin 1.14.1 14663 * https://jqueryui.com 14664 * 14665 * Copyright OpenJS Foundation and other contributors 14666 * Released under the MIT license. 14667 * https://jquery.org/license 14668 */ 14669 14670//>>label: Form Reset Mixin 14671//>>group: Core 14672//>>description: Refresh input widgets when their form is reset 14673//>>docs: https://api.jqueryui.com/form-reset-mixin/ 14674 14675 14676var formResetMixin = $.ui.formResetMixin = { 14677 _formResetHandler: function() { 14678 var form = $( this ); 14679 14680 // Wait for the form reset to actually happen before refreshing 14681 setTimeout( function() { 14682 var instances = form.data( "ui-form-reset-instances" ); 14683 $.each( instances, function() { 14684 this.refresh(); 14685 } ); 14686 } ); 14687 }, 14688 14689 _bindFormResetHandler: function() { 14690 this.form = $( this.element.prop( "form" ) ); 14691 if ( !this.form.length ) { 14692 return; 14693 } 14694 14695 var instances = this.form.data( "ui-form-reset-instances" ) || []; 14696 if ( !instances.length ) { 14697 14698 // We don't use _on() here because we use a single event handler per form 14699 this.form.on( "reset.ui-form-reset", this._formResetHandler ); 14700 } 14701 instances.push( this ); 14702 this.form.data( "ui-form-reset-instances", instances ); 14703 }, 14704 14705 _unbindFormResetHandler: function() { 14706 if ( !this.form.length ) { 14707 return; 14708 } 14709 14710 var instances = this.form.data( "ui-form-reset-instances" ); 14711 instances.splice( $.inArray( this, instances ), 1 ); 14712 if ( instances.length ) { 14713 this.form.data( "ui-form-reset-instances", instances ); 14714 } else { 14715 this.form 14716 .removeData( "ui-form-reset-instances" ) 14717 .off( "reset.ui-form-reset" ); 14718 } 14719 } 14720}; 14721 14722 14723/*! 14724 * jQuery UI Legacy jQuery Core patches 1.14.1 14725 * https://jqueryui.com 14726 * 14727 * Copyright OpenJS Foundation and other contributors 14728 * Released under the MIT license. 14729 * https://jquery.org/license 14730 * 14731 */ 14732 14733//>>label: Legacy jQuery Core patches 14734//>>group: Core 14735//>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated) 14736 14737 14738// Support: jQuery 2.2.x or older. 14739// This method has been defined in jQuery 3.0.0. 14740// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js 14741if ( !$.escapeSelector ) { 14742 $.escapeSelector = function( id ) { 14743 return CSS.escape( id + "" ); 14744 }; 14745} 14746 14747// Support: jQuery 3.4.x or older 14748// These methods have been defined in jQuery 3.5.0. 14749if ( !$.fn.even || !$.fn.odd ) { 14750 $.fn.extend( { 14751 even: function() { 14752 return this.filter( function( i ) { 14753 return i % 2 === 0; 14754 } ); 14755 }, 14756 odd: function() { 14757 return this.filter( function( i ) { 14758 return i % 2 === 1; 14759 } ); 14760 } 14761 } ); 14762} 14763 14764; 14765/*! 14766 * jQuery UI Keycode 1.14.1 14767 * https://jqueryui.com 14768 * 14769 * Copyright OpenJS Foundation and other contributors 14770 * Released under the MIT license. 14771 * https://jquery.org/license 14772 */ 14773 14774//>>label: Keycode 14775//>>group: Core 14776//>>description: Provide keycodes as keynames 14777//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/ 14778 14779 14780var keycode = $.ui.keyCode = { 14781 BACKSPACE: 8, 14782 COMMA: 188, 14783 DELETE: 46, 14784 DOWN: 40, 14785 END: 35, 14786 ENTER: 13, 14787 ESCAPE: 27, 14788 HOME: 36, 14789 LEFT: 37, 14790 PAGE_DOWN: 34, 14791 PAGE_UP: 33, 14792 PERIOD: 190, 14793 RIGHT: 39, 14794 SPACE: 32, 14795 TAB: 9, 14796 UP: 38 14797}; 14798 14799 14800/*! 14801 * jQuery UI Labels 1.14.1 14802 * https://jqueryui.com 14803 * 14804 * Copyright OpenJS Foundation and other contributors 14805 * Released under the MIT license. 14806 * https://jquery.org/license 14807 */ 14808 14809//>>label: labels 14810//>>group: Core 14811//>>description: Find all the labels associated with a given input 14812//>>docs: https://api.jqueryui.com/labels/ 14813 14814 14815var labels = $.fn.labels = function() { 14816 var ancestor, selector, id, labels, ancestors; 14817 14818 if ( !this.length ) { 14819 return this.pushStack( [] ); 14820 } 14821 14822 // Check control.labels first 14823 if ( this[ 0 ].labels && this[ 0 ].labels.length ) { 14824 return this.pushStack( this[ 0 ].labels ); 14825 } 14826 14827 // If `control.labels` is empty - e.g. inside of document fragments - find 14828 // the labels manually 14829 labels = this.eq( 0 ).parents( "label" ); 14830 14831 // Look for the label based on the id 14832 id = this.attr( "id" ); 14833 if ( id ) { 14834 14835 // We don't search against the document in case the element 14836 // is disconnected from the DOM 14837 ancestor = this.eq( 0 ).parents().last(); 14838 14839 // Get a full set of top level ancestors 14840 ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() ); 14841 14842 // Create a selector for the label based on the id 14843 selector = "label[for='" + CSS.escape( id ) + "']"; 14844 14845 labels = labels.add( ancestors.find( selector ).addBack( selector ) ); 14846 14847 } 14848 14849 // Return whatever we have found for labels 14850 return this.pushStack( labels ); 14851}; 14852 14853 14854/*! 14855 * jQuery UI Scroll Parent 1.14.1 14856 * https://jqueryui.com 14857 * 14858 * Copyright OpenJS Foundation and other contributors 14859 * Released under the MIT license. 14860 * https://jquery.org/license 14861 */ 14862 14863//>>label: scrollParent 14864//>>group: Core 14865//>>description: Get the closest ancestor element that is scrollable. 14866//>>docs: https://api.jqueryui.com/scrollParent/ 14867 14868 14869var scrollParent = $.fn.scrollParent = function( includeHidden ) { 14870 var position = this.css( "position" ), 14871 excludeStaticParent = position === "absolute", 14872 overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, 14873 scrollParent = this.parents().filter( function() { 14874 var parent = $( this ); 14875 if ( excludeStaticParent && parent.css( "position" ) === "static" ) { 14876 return false; 14877 } 14878 return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + 14879 parent.css( "overflow-x" ) ); 14880 } ).eq( 0 ); 14881 14882 return position === "fixed" || !scrollParent.length ? 14883 $( this[ 0 ].ownerDocument || document ) : 14884 scrollParent; 14885}; 14886 14887 14888/*! 14889 * jQuery UI Tabbable 1.14.1 14890 * https://jqueryui.com 14891 * 14892 * Copyright OpenJS Foundation and other contributors 14893 * Released under the MIT license. 14894 * https://jquery.org/license 14895 */ 14896 14897//>>label: :tabbable Selector 14898//>>group: Core 14899//>>description: Selects elements which can be tabbed to. 14900//>>docs: https://api.jqueryui.com/tabbable-selector/ 14901 14902 14903var tabbable = $.extend( $.expr.pseudos, { 14904 tabbable: function( element ) { 14905 var tabIndex = $.attr( element, "tabindex" ), 14906 hasTabindex = tabIndex != null; 14907 return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex ); 14908 } 14909} ); 14910 14911 14912/*! 14913 * jQuery UI Unique ID 1.14.1 14914 * https://jqueryui.com 14915 * 14916 * Copyright OpenJS Foundation and other contributors 14917 * Released under the MIT license. 14918 * https://jquery.org/license 14919 */ 14920 14921//>>label: uniqueId 14922//>>group: Core 14923//>>description: Functions to generate and remove uniqueId's 14924//>>docs: https://api.jqueryui.com/uniqueId/ 14925 14926 14927var uniqueId = $.fn.extend( { 14928 uniqueId: ( function() { 14929 var uuid = 0; 14930 14931 return function() { 14932 return this.each( function() { 14933 if ( !this.id ) { 14934 this.id = "ui-id-" + ( ++uuid ); 14935 } 14936 } ); 14937 }; 14938 } )(), 14939 14940 removeUniqueId: function() { 14941 return this.each( function() { 14942 if ( /^ui-id-\d+$/.test( this.id ) ) { 14943 $( this ).removeAttr( "id" ); 14944 } 14945 } ); 14946 } 14947} ); 14948 14949 14950/*! 14951 * jQuery UI Accordion 1.14.1 14952 * https://jqueryui.com 14953 * 14954 * Copyright OpenJS Foundation and other contributors 14955 * Released under the MIT license. 14956 * https://jquery.org/license 14957 */ 14958 14959//>>label: Accordion 14960//>>group: Widgets 14961/* eslint-disable max-len */ 14962//>>description: Displays collapsible content panels for presenting information in a limited amount of space. 14963/* eslint-enable max-len */ 14964//>>docs: https://api.jqueryui.com/accordion/ 14965//>>demos: https://jqueryui.com/accordion/ 14966//>>css.structure: ../../themes/base/core.css 14967//>>css.structure: ../../themes/base/accordion.css 14968//>>css.theme: ../../themes/base/theme.css 14969 14970 14971var widgetsAccordion = $.widget( "ui.accordion", { 14972 version: "1.14.1", 14973 options: { 14974 active: 0, 14975 animate: {}, 14976 classes: { 14977 "ui-accordion-header": "ui-corner-top", 14978 "ui-accordion-header-collapsed": "ui-corner-all", 14979 "ui-accordion-content": "ui-corner-bottom" 14980 }, 14981 collapsible: false, 14982 event: "click", 14983 header: function( elem ) { 14984 return elem 14985 .find( "> li > :first-child" ) 14986 .add( 14987 elem.find( "> :not(li)" ) 14988 14989 // Support: jQuery <3.5 only 14990 // We could use `.even()` but that's unavailable in older jQuery. 14991 .filter( function( i ) { 14992 return i % 2 === 0; 14993 } ) 14994 ); 14995 }, 14996 heightStyle: "auto", 14997 icons: { 14998 activeHeader: "ui-icon-triangle-1-s", 14999 header: "ui-icon-triangle-1-e" 15000 }, 15001 15002 // Callbacks 15003 activate: null, 15004 beforeActivate: null 15005 }, 15006 15007 hideProps: { 15008 borderTopWidth: "hide", 15009 borderBottomWidth: "hide", 15010 paddingTop: "hide", 15011 paddingBottom: "hide", 15012 height: "hide" 15013 }, 15014 15015 showProps: { 15016 borderTopWidth: "show", 15017 borderBottomWidth: "show", 15018 paddingTop: "show", 15019 paddingBottom: "show", 15020 height: "show" 15021 }, 15022 15023 _create: function() { 15024 var options = this.options; 15025 15026 this.prevShow = this.prevHide = $(); 15027 this._addClass( "ui-accordion", "ui-widget ui-helper-reset" ); 15028 this.element.attr( "role", "tablist" ); 15029 15030 // Don't allow collapsible: false and active: false / null 15031 if ( !options.collapsible && ( options.active === false || options.active == null ) ) { 15032 options.active = 0; 15033 } 15034 15035 this._processPanels(); 15036 15037 // handle negative values 15038 if ( options.active < 0 ) { 15039 options.active += this.headers.length; 15040 } 15041 this._refresh(); 15042 }, 15043 15044 _getCreateEventData: function() { 15045 return { 15046 header: this.active, 15047 panel: !this.active.length ? $() : this.active.next() 15048 }; 15049 }, 15050 15051 _createIcons: function() { 15052 var icon, children, 15053 icons = this.options.icons; 15054 15055 if ( icons ) { 15056 icon = $( "<span>" ); 15057 this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header ); 15058 icon.prependTo( this.headers ); 15059 children = this.active.children( ".ui-accordion-header-icon" ); 15060 this._removeClass( children, icons.header ) 15061 ._addClass( children, null, icons.activeHeader ) 15062 ._addClass( this.headers, "ui-accordion-icons" ); 15063 } 15064 }, 15065 15066 _destroyIcons: function() { 15067 this._removeClass( this.headers, "ui-accordion-icons" ); 15068 this.headers.children( ".ui-accordion-header-icon" ).remove(); 15069 }, 15070 15071 _destroy: function() { 15072 var contents; 15073 15074 // Clean up main element 15075 this.element.removeAttr( "role" ); 15076 15077 // Clean up headers 15078 this.headers 15079 .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" ) 15080 .removeUniqueId(); 15081 15082 this._destroyIcons(); 15083 15084 // Clean up content panels 15085 contents = this.headers.next() 15086 .css( "display", "" ) 15087 .removeAttr( "role aria-hidden aria-labelledby" ) 15088 .removeUniqueId(); 15089 15090 if ( this.options.heightStyle !== "content" ) { 15091 contents.css( "height", "" ); 15092 } 15093 }, 15094 15095 _setOption: function( key, value ) { 15096 if ( key === "active" ) { 15097 15098 // _activate() will handle invalid values and update this.options 15099 this._activate( value ); 15100 return; 15101 } 15102 15103 if ( key === "event" ) { 15104 if ( this.options.event ) { 15105 this._off( this.headers, this.options.event ); 15106 } 15107 this._setupEvents( value ); 15108 } 15109 15110 this._super( key, value ); 15111 15112 // Setting collapsible: false while collapsed; open first panel 15113 if ( key === "collapsible" && !value && this.options.active === false ) { 15114 this._activate( 0 ); 15115 } 15116 15117 if ( key === "icons" ) { 15118 this._destroyIcons(); 15119 if ( value ) { 15120 this._createIcons(); 15121 } 15122 } 15123 }, 15124 15125 _setOptionDisabled: function( value ) { 15126 this._super( value ); 15127 15128 this.element.attr( "aria-disabled", value ); 15129 this._toggleClass( null, "ui-state-disabled", !!value ); 15130 }, 15131 15132 _keydown: function( event ) { 15133 if ( event.altKey || event.ctrlKey ) { 15134 return; 15135 } 15136 15137 var keyCode = $.ui.keyCode, 15138 length = this.headers.length, 15139 currentIndex = this.headers.index( event.target ), 15140 toFocus = false; 15141 15142 switch ( event.keyCode ) { 15143 case keyCode.RIGHT: 15144 case keyCode.DOWN: 15145 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 15146 break; 15147 case keyCode.LEFT: 15148 case keyCode.UP: 15149 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 15150 break; 15151 case keyCode.SPACE: 15152 case keyCode.ENTER: 15153 this._eventHandler( event ); 15154 break; 15155 case keyCode.HOME: 15156 toFocus = this.headers[ 0 ]; 15157 break; 15158 case keyCode.END: 15159 toFocus = this.headers[ length - 1 ]; 15160 break; 15161 } 15162 15163 if ( toFocus ) { 15164 $( event.target ).attr( "tabIndex", -1 ); 15165 $( toFocus ).attr( "tabIndex", 0 ); 15166 $( toFocus ).trigger( "focus" ); 15167 event.preventDefault(); 15168 } 15169 }, 15170 15171 _panelKeyDown: function( event ) { 15172 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { 15173 $( event.currentTarget ).prev().trigger( "focus" ); 15174 } 15175 }, 15176 15177 refresh: function() { 15178 var options = this.options; 15179 this._processPanels(); 15180 15181 // Was collapsed or no panel 15182 if ( ( options.active === false && options.collapsible === true ) || 15183 !this.headers.length ) { 15184 options.active = false; 15185 this.active = $(); 15186 15187 // active false only when collapsible is true 15188 } else if ( options.active === false ) { 15189 this._activate( 0 ); 15190 15191 // was active, but active panel is gone 15192 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 15193 15194 // all remaining panel are disabled 15195 if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) { 15196 options.active = false; 15197 this.active = $(); 15198 15199 // activate previous panel 15200 } else { 15201 this._activate( Math.max( 0, options.active - 1 ) ); 15202 } 15203 15204 // was active, active panel still exists 15205 } else { 15206 15207 // make sure active index is correct 15208 options.active = this.headers.index( this.active ); 15209 } 15210 15211 this._destroyIcons(); 15212 15213 this._refresh(); 15214 }, 15215 15216 _processPanels: function() { 15217 var prevHeaders = this.headers, 15218 prevPanels = this.panels; 15219 15220 if ( typeof this.options.header === "function" ) { 15221 this.headers = this.options.header( this.element ); 15222 } else { 15223 this.headers = this.element.find( this.options.header ); 15224 } 15225 this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed", 15226 "ui-state-default" ); 15227 15228 this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide(); 15229 this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" ); 15230 15231 // Avoid memory leaks (#10056) 15232 if ( prevPanels ) { 15233 this._off( prevHeaders.not( this.headers ) ); 15234 this._off( prevPanels.not( this.panels ) ); 15235 } 15236 }, 15237 15238 _refresh: function() { 15239 var maxHeight, 15240 options = this.options, 15241 heightStyle = options.heightStyle, 15242 parent = this.element.parent(); 15243 15244 this.active = this._findActive( options.active ); 15245 this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" ) 15246 ._removeClass( this.active, "ui-accordion-header-collapsed" ); 15247 this._addClass( this.active.next(), "ui-accordion-content-active" ); 15248 this.active.next().show(); 15249 15250 this.headers 15251 .attr( "role", "tab" ) 15252 .each( function() { 15253 var header = $( this ), 15254 headerId = header.uniqueId().attr( "id" ), 15255 panel = header.next(), 15256 panelId = panel.uniqueId().attr( "id" ); 15257 header.attr( "aria-controls", panelId ); 15258 panel.attr( "aria-labelledby", headerId ); 15259 } ) 15260 .next() 15261 .attr( "role", "tabpanel" ); 15262 15263 this.headers 15264 .not( this.active ) 15265 .attr( { 15266 "aria-selected": "false", 15267 "aria-expanded": "false", 15268 tabIndex: -1 15269 } ) 15270 .next() 15271 .attr( { 15272 "aria-hidden": "true" 15273 } ) 15274 .hide(); 15275 15276 // Make sure at least one header is in the tab order 15277 if ( !this.active.length ) { 15278 this.headers.eq( 0 ).attr( "tabIndex", 0 ); 15279 } else { 15280 this.active.attr( { 15281 "aria-selected": "true", 15282 "aria-expanded": "true", 15283 tabIndex: 0 15284 } ) 15285 .next() 15286 .attr( { 15287 "aria-hidden": "false" 15288 } ); 15289 } 15290 15291 this._createIcons(); 15292 15293 this._setupEvents( options.event ); 15294 15295 if ( heightStyle === "fill" ) { 15296 maxHeight = parent.height(); 15297 this.element.siblings( ":visible" ).each( function() { 15298 var elem = $( this ), 15299 position = elem.css( "position" ); 15300 15301 if ( position === "absolute" || position === "fixed" ) { 15302 return; 15303 } 15304 maxHeight -= elem.outerHeight( true ); 15305 } ); 15306 15307 this.headers.each( function() { 15308 maxHeight -= $( this ).outerHeight( true ); 15309 } ); 15310 15311 this.headers.next() 15312 .each( function() { 15313 $( this ).height( Math.max( 0, maxHeight - 15314 $( this ).innerHeight() + $( this ).height() ) ); 15315 } ) 15316 .css( "overflow", "auto" ); 15317 } else if ( heightStyle === "auto" ) { 15318 maxHeight = 0; 15319 this.headers.next() 15320 .each( function() { 15321 var isVisible = $( this ).is( ":visible" ); 15322 if ( !isVisible ) { 15323 $( this ).show(); 15324 } 15325 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); 15326 if ( !isVisible ) { 15327 $( this ).hide(); 15328 } 15329 } ) 15330 .height( maxHeight ); 15331 } 15332 }, 15333 15334 _activate: function( index ) { 15335 var active = this._findActive( index )[ 0 ]; 15336 15337 // Trying to activate the already active panel 15338 if ( active === this.active[ 0 ] ) { 15339 return; 15340 } 15341 15342 // Trying to collapse, simulate a click on the currently active header 15343 active = active || this.active[ 0 ]; 15344 15345 this._eventHandler( { 15346 target: active, 15347 currentTarget: active, 15348 preventDefault: $.noop 15349 } ); 15350 }, 15351 15352 _findActive: function( selector ) { 15353 return typeof selector === "number" ? this.headers.eq( selector ) : $(); 15354 }, 15355 15356 _setupEvents: function( event ) { 15357 var events = { 15358 keydown: "_keydown" 15359 }; 15360 if ( event ) { 15361 $.each( event.split( " " ), function( index, eventName ) { 15362 events[ eventName ] = "_eventHandler"; 15363 } ); 15364 } 15365 15366 this._off( this.headers.add( this.headers.next() ) ); 15367 this._on( this.headers, events ); 15368 this._on( this.headers.next(), { keydown: "_panelKeyDown" } ); 15369 this._hoverable( this.headers ); 15370 this._focusable( this.headers ); 15371 }, 15372 15373 _eventHandler: function( event ) { 15374 var activeChildren, clickedChildren, 15375 options = this.options, 15376 active = this.active, 15377 clicked = $( event.currentTarget ), 15378 clickedIsActive = clicked[ 0 ] === active[ 0 ], 15379 collapsing = clickedIsActive && options.collapsible, 15380 toShow = collapsing ? $() : clicked.next(), 15381 toHide = active.next(), 15382 eventData = { 15383 oldHeader: active, 15384 oldPanel: toHide, 15385 newHeader: collapsing ? $() : clicked, 15386 newPanel: toShow 15387 }; 15388 15389 event.preventDefault(); 15390 15391 if ( 15392 15393 // click on active header, but not collapsible 15394 ( clickedIsActive && !options.collapsible ) || 15395 15396 // allow canceling activation 15397 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 15398 return; 15399 } 15400 15401 options.active = collapsing ? false : this.headers.index( clicked ); 15402 15403 // When the call to ._toggle() comes after the class changes 15404 // it causes a very odd bug in IE 8 (see #6720) 15405 this.active = clickedIsActive ? $() : clicked; 15406 this._toggle( eventData ); 15407 15408 // Switch classes 15409 // corner classes on the previously active header stay after the animation 15410 this._removeClass( active, "ui-accordion-header-active", "ui-state-active" ); 15411 if ( options.icons ) { 15412 activeChildren = active.children( ".ui-accordion-header-icon" ); 15413 this._removeClass( activeChildren, null, options.icons.activeHeader ) 15414 ._addClass( activeChildren, null, options.icons.header ); 15415 } 15416 15417 if ( !clickedIsActive ) { 15418 this._removeClass( clicked, "ui-accordion-header-collapsed" ) 15419 ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" ); 15420 if ( options.icons ) { 15421 clickedChildren = clicked.children( ".ui-accordion-header-icon" ); 15422 this._removeClass( clickedChildren, null, options.icons.header ) 15423 ._addClass( clickedChildren, null, options.icons.activeHeader ); 15424 } 15425 15426 this._addClass( clicked.next(), "ui-accordion-content-active" ); 15427 } 15428 }, 15429 15430 _toggle: function( data ) { 15431 var toShow = data.newPanel, 15432 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 15433 15434 // Handle activating a panel during the animation for another activation 15435 this.prevShow.add( this.prevHide ).stop( true, true ); 15436 this.prevShow = toShow; 15437 this.prevHide = toHide; 15438 15439 if ( this.options.animate ) { 15440 this._animate( toShow, toHide, data ); 15441 } else { 15442 toHide.hide(); 15443 toShow.show(); 15444 this._toggleComplete( data ); 15445 } 15446 15447 toHide.attr( { 15448 "aria-hidden": "true" 15449 } ); 15450 toHide.prev().attr( { 15451 "aria-selected": "false", 15452 "aria-expanded": "false" 15453 } ); 15454 15455 // if we're switching panels, remove the old header from the tab order 15456 // if we're opening from collapsed state, remove the previous header from the tab order 15457 // if we're collapsing, then keep the collapsing header in the tab order 15458 if ( toShow.length && toHide.length ) { 15459 toHide.prev().attr( { 15460 "tabIndex": -1, 15461 "aria-expanded": "false" 15462 } ); 15463 } else if ( toShow.length ) { 15464 this.headers.filter( function() { 15465 return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0; 15466 } ) 15467 .attr( "tabIndex", -1 ); 15468 } 15469 15470 toShow 15471 .attr( "aria-hidden", "false" ) 15472 .prev() 15473 .attr( { 15474 "aria-selected": "true", 15475 "aria-expanded": "true", 15476 tabIndex: 0 15477 } ); 15478 }, 15479 15480 _animate: function( toShow, toHide, data ) { 15481 var total, easing, duration, 15482 that = this, 15483 adjust = 0, 15484 boxSizing = toShow.css( "box-sizing" ), 15485 down = toShow.length && 15486 ( !toHide.length || ( toShow.index() < toHide.index() ) ), 15487 animate = this.options.animate || {}, 15488 options = down && animate.down || animate, 15489 complete = function() { 15490 that._toggleComplete( data ); 15491 }; 15492 15493 if ( typeof options === "number" ) { 15494 duration = options; 15495 } 15496 if ( typeof options === "string" ) { 15497 easing = options; 15498 } 15499 15500 // fall back from options to animation in case of partial down settings 15501 easing = easing || options.easing || animate.easing; 15502 duration = duration || options.duration || animate.duration; 15503 15504 if ( !toHide.length ) { 15505 return toShow.animate( this.showProps, duration, easing, complete ); 15506 } 15507 if ( !toShow.length ) { 15508 return toHide.animate( this.hideProps, duration, easing, complete ); 15509 } 15510 15511 total = toShow.show().outerHeight(); 15512 toHide.animate( this.hideProps, { 15513 duration: duration, 15514 easing: easing, 15515 step: function( now, fx ) { 15516 fx.now = Math.round( now ); 15517 } 15518 } ); 15519 toShow 15520 .hide() 15521 .animate( this.showProps, { 15522 duration: duration, 15523 easing: easing, 15524 complete: complete, 15525 step: function( now, fx ) { 15526 fx.now = Math.round( now ); 15527 if ( fx.prop !== "height" ) { 15528 if ( boxSizing === "content-box" ) { 15529 adjust += fx.now; 15530 } 15531 } else if ( that.options.heightStyle !== "content" ) { 15532 fx.now = Math.round( total - toHide.outerHeight() - adjust ); 15533 adjust = 0; 15534 } 15535 } 15536 } ); 15537 }, 15538 15539 _toggleComplete: function( data ) { 15540 var toHide = data.oldPanel, 15541 prev = toHide.prev(); 15542 15543 this._removeClass( toHide, "ui-accordion-content-active" ); 15544 this._removeClass( prev, "ui-accordion-header-active" ) 15545 ._addClass( prev, "ui-accordion-header-collapsed" ); 15546 15547 this._trigger( "activate", null, data ); 15548 } 15549} ); 15550 15551 15552/*! 15553 * jQuery UI Menu 1.14.1 15554 * https://jqueryui.com 15555 * 15556 * Copyright OpenJS Foundation and other contributors 15557 * Released under the MIT license. 15558 * https://jquery.org/license 15559 */ 15560 15561//>>label: Menu 15562//>>group: Widgets 15563//>>description: Creates nestable menus. 15564//>>docs: https://api.jqueryui.com/menu/ 15565//>>demos: https://jqueryui.com/menu/ 15566//>>css.structure: ../../themes/base/core.css 15567//>>css.structure: ../../themes/base/menu.css 15568//>>css.theme: ../../themes/base/theme.css 15569 15570 15571var widgetsMenu = $.widget( "ui.menu", { 15572 version: "1.14.1", 15573 defaultElement: "<ul>", 15574 delay: 300, 15575 options: { 15576 icons: { 15577 submenu: "ui-icon-caret-1-e" 15578 }, 15579 items: "> *", 15580 menus: "ul", 15581 position: { 15582 my: "left top", 15583 at: "right top" 15584 }, 15585 role: "menu", 15586 15587 // Callbacks 15588 blur: null, 15589 focus: null, 15590 select: null 15591 }, 15592 15593 _create: function() { 15594 this.activeMenu = this.element; 15595 15596 // Flag used to prevent firing of the click handler 15597 // as the event bubbles up through nested menus 15598 this.mouseHandled = false; 15599 this.lastMousePosition = { x: null, y: null }; 15600 this.element 15601 .uniqueId() 15602 .attr( { 15603 role: this.options.role, 15604 tabIndex: 0 15605 } ); 15606 15607 this._addClass( "ui-menu", "ui-widget ui-widget-content" ); 15608 this._on( { 15609 15610 // Prevent focus from sticking to links inside menu after clicking 15611 // them (focus should always stay on UL during navigation). 15612 "mousedown .ui-menu-item": function( event ) { 15613 event.preventDefault(); 15614 15615 this._activateItem( event ); 15616 }, 15617 "click .ui-menu-item": function( event ) { 15618 var target = $( event.target ); 15619 var active = $( this.document[ 0 ].activeElement ); 15620 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { 15621 this.select( event ); 15622 15623 // Only set the mouseHandled flag if the event will bubble, see #9469. 15624 if ( !event.isPropagationStopped() ) { 15625 this.mouseHandled = true; 15626 } 15627 15628 // Open submenu on click 15629 if ( target.has( ".ui-menu" ).length ) { 15630 this.expand( event ); 15631 } else if ( !this.element.is( ":focus" ) && 15632 active.closest( ".ui-menu" ).length ) { 15633 15634 // Redirect focus to the menu 15635 this.element.trigger( "focus", [ true ] ); 15636 15637 // If the active item is on the top level, let it stay active. 15638 // Otherwise, blur the active item since it is no longer visible. 15639 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { 15640 clearTimeout( this.timer ); 15641 } 15642 } 15643 } 15644 }, 15645 "mouseenter .ui-menu-item": "_activateItem", 15646 "mousemove .ui-menu-item": "_activateItem", 15647 mouseleave: "collapseAll", 15648 "mouseleave .ui-menu": "collapseAll", 15649 focus: function( event, keepActiveItem ) { 15650 15651 // If there's already an active item, keep it active 15652 // If not, activate the first item 15653 var item = this.active || this._menuItems().first(); 15654 15655 if ( !keepActiveItem ) { 15656 this.focus( event, item ); 15657 } 15658 }, 15659 blur: function( event ) { 15660 this._delay( function() { 15661 var notContained = !$.contains( 15662 this.element[ 0 ], 15663 this.document[ 0 ].activeElement 15664 ); 15665 if ( notContained ) { 15666 this.collapseAll( event ); 15667 } 15668 } ); 15669 }, 15670 keydown: "_keydown" 15671 } ); 15672 15673 this.refresh(); 15674 15675 // Clicks outside of a menu collapse any open menus 15676 this._on( this.document, { 15677 click: function( event ) { 15678 if ( this._closeOnDocumentClick( event ) ) { 15679 this.collapseAll( event, true ); 15680 } 15681 15682 // Reset the mouseHandled flag 15683 this.mouseHandled = false; 15684 } 15685 } ); 15686 }, 15687 15688 _activateItem: function( event ) { 15689 15690 // Ignore mouse events while typeahead is active, see #10458. 15691 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse 15692 // is over an item in the menu 15693 if ( this.previousFilter ) { 15694 return; 15695 } 15696 15697 // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356) 15698 if ( event.clientX === this.lastMousePosition.x && 15699 event.clientY === this.lastMousePosition.y ) { 15700 return; 15701 } 15702 15703 this.lastMousePosition = { 15704 x: event.clientX, 15705 y: event.clientY 15706 }; 15707 15708 var actualTarget = $( event.target ).closest( ".ui-menu-item" ), 15709 target = $( event.currentTarget ); 15710 15711 // Ignore bubbled events on parent items, see #11641 15712 if ( actualTarget[ 0 ] !== target[ 0 ] ) { 15713 return; 15714 } 15715 15716 // If the item is already active, there's nothing to do 15717 if ( target.is( ".ui-state-active" ) ) { 15718 return; 15719 } 15720 15721 // Remove ui-state-active class from siblings of the newly focused menu item 15722 // to avoid a jump caused by adjacent elements both having a class with a border 15723 this._removeClass( target.siblings().children( ".ui-state-active" ), 15724 null, "ui-state-active" ); 15725 this.focus( event, target ); 15726 }, 15727 15728 _destroy: function() { 15729 var items = this.element.find( ".ui-menu-item" ) 15730 .removeAttr( "role aria-disabled" ), 15731 submenus = items.children( ".ui-menu-item-wrapper" ) 15732 .removeUniqueId() 15733 .removeAttr( "tabIndex role aria-haspopup" ); 15734 15735 // Destroy (sub)menus 15736 this.element 15737 .removeAttr( "aria-activedescendant" ) 15738 .find( ".ui-menu" ).addBack() 15739 .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " + 15740 "tabIndex" ) 15741 .removeUniqueId() 15742 .show(); 15743 15744 submenus.children().each( function() { 15745 var elem = $( this ); 15746 if ( elem.data( "ui-menu-submenu-caret" ) ) { 15747 elem.remove(); 15748 } 15749 } ); 15750 }, 15751 15752 _keydown: function( event ) { 15753 var match, prev, character, skip, 15754 preventDefault = true; 15755 15756 switch ( event.keyCode ) { 15757 case $.ui.keyCode.PAGE_UP: 15758 this.previousPage( event ); 15759 break; 15760 case $.ui.keyCode.PAGE_DOWN: 15761 this.nextPage( event ); 15762 break; 15763 case $.ui.keyCode.HOME: 15764 this._move( "first", "first", event ); 15765 break; 15766 case $.ui.keyCode.END: 15767 this._move( "last", "last", event ); 15768 break; 15769 case $.ui.keyCode.UP: 15770 this.previous( event ); 15771 break; 15772 case $.ui.keyCode.DOWN: 15773 this.next( event ); 15774 break; 15775 case $.ui.keyCode.LEFT: 15776 this.collapse( event ); 15777 break; 15778 case $.ui.keyCode.RIGHT: 15779 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 15780 this.expand( event ); 15781 } 15782 break; 15783 case $.ui.keyCode.ENTER: 15784 case $.ui.keyCode.SPACE: 15785 this._activate( event ); 15786 break; 15787 case $.ui.keyCode.ESCAPE: 15788 this.collapse( event ); 15789 break; 15790 default: 15791 preventDefault = false; 15792 prev = this.previousFilter || ""; 15793 skip = false; 15794 15795 // Support number pad values 15796 character = event.keyCode >= 96 && event.keyCode <= 105 ? 15797 ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode ); 15798 15799 clearTimeout( this.filterTimer ); 15800 15801 if ( character === prev ) { 15802 skip = true; 15803 } else { 15804 character = prev + character; 15805 } 15806 15807 match = this._filterMenuItems( character ); 15808 match = skip && match.index( this.active.next() ) !== -1 ? 15809 this.active.nextAll( ".ui-menu-item" ) : 15810 match; 15811 15812 // If no matches on the current filter, reset to the last character pressed 15813 // to move down the menu to the first item that starts with that character 15814 if ( !match.length ) { 15815 character = String.fromCharCode( event.keyCode ); 15816 match = this._filterMenuItems( character ); 15817 } 15818 15819 if ( match.length ) { 15820 this.focus( event, match ); 15821 this.previousFilter = character; 15822 this.filterTimer = this._delay( function() { 15823 delete this.previousFilter; 15824 }, 1000 ); 15825 } else { 15826 delete this.previousFilter; 15827 } 15828 } 15829 15830 if ( preventDefault ) { 15831 event.preventDefault(); 15832 } 15833 }, 15834 15835 _activate: function( event ) { 15836 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 15837 if ( this.active.children( "[aria-haspopup='true']" ).length ) { 15838 this.expand( event ); 15839 } else { 15840 this.select( event ); 15841 } 15842 } 15843 }, 15844 15845 refresh: function() { 15846 var menus, items, newSubmenus, newItems, newWrappers, 15847 that = this, 15848 icon = this.options.icons.submenu, 15849 submenus = this.element.find( this.options.menus ); 15850 15851 this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length ); 15852 15853 // Initialize nested menus 15854 newSubmenus = submenus.filter( ":not(.ui-menu)" ) 15855 .hide() 15856 .attr( { 15857 role: this.options.role, 15858 "aria-hidden": "true", 15859 "aria-expanded": "false" 15860 } ) 15861 .each( function() { 15862 var menu = $( this ), 15863 item = menu.prev(), 15864 submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true ); 15865 15866 that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon ); 15867 item 15868 .attr( "aria-haspopup", "true" ) 15869 .prepend( submenuCaret ); 15870 menu.attr( "aria-labelledby", item.attr( "id" ) ); 15871 } ); 15872 15873 this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" ); 15874 15875 menus = submenus.add( this.element ); 15876 items = menus.find( this.options.items ); 15877 15878 // Initialize menu-items containing spaces and/or dashes only as dividers 15879 items.not( ".ui-menu-item" ).each( function() { 15880 var item = $( this ); 15881 if ( that._isDivider( item ) ) { 15882 that._addClass( item, "ui-menu-divider", "ui-widget-content" ); 15883 } 15884 } ); 15885 15886 // Don't refresh list items that are already adapted 15887 newItems = items.not( ".ui-menu-item, .ui-menu-divider" ); 15888 newWrappers = newItems.children() 15889 .not( ".ui-menu" ) 15890 .uniqueId() 15891 .attr( { 15892 tabIndex: -1, 15893 role: this._itemRole() 15894 } ); 15895 this._addClass( newItems, "ui-menu-item" ) 15896 ._addClass( newWrappers, "ui-menu-item-wrapper" ); 15897 15898 // Add aria-disabled attribute to any disabled menu item 15899 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); 15900 15901 // If the active item has been removed, blur the menu 15902 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 15903 this.blur(); 15904 } 15905 }, 15906 15907 _itemRole: function() { 15908 return { 15909 menu: "menuitem", 15910 listbox: "option" 15911 }[ this.options.role ]; 15912 }, 15913 15914 _setOption: function( key, value ) { 15915 if ( key === "icons" ) { 15916 var icons = this.element.find( ".ui-menu-icon" ); 15917 this._removeClass( icons, null, this.options.icons.submenu ) 15918 ._addClass( icons, null, value.submenu ); 15919 } 15920 this._super( key, value ); 15921 }, 15922 15923 _setOptionDisabled: function( value ) { 15924 this._super( value ); 15925 15926 this.element.attr( "aria-disabled", String( value ) ); 15927 this._toggleClass( null, "ui-state-disabled", !!value ); 15928 }, 15929 15930 focus: function( event, item ) { 15931 var nested, focused, activeParent; 15932 this.blur( event, event && event.type === "focus" ); 15933 15934 this._scrollIntoView( item ); 15935 15936 this.active = item.first(); 15937 15938 focused = this.active.children( ".ui-menu-item-wrapper" ); 15939 this._addClass( focused, null, "ui-state-active" ); 15940 15941 // Only update aria-activedescendant if there's a role 15942 // otherwise we assume focus is managed elsewhere 15943 if ( this.options.role ) { 15944 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); 15945 } 15946 15947 // Highlight active parent menu item, if any 15948 activeParent = this.active 15949 .parent() 15950 .closest( ".ui-menu-item" ) 15951 .children( ".ui-menu-item-wrapper" ); 15952 this._addClass( activeParent, null, "ui-state-active" ); 15953 15954 if ( event && event.type === "keydown" ) { 15955 this._close(); 15956 } else { 15957 this.timer = this._delay( function() { 15958 this._close(); 15959 }, this.delay ); 15960 } 15961 15962 nested = item.children( ".ui-menu" ); 15963 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { 15964 this._startOpening( nested ); 15965 } 15966 this.activeMenu = item.parent(); 15967 15968 this._trigger( "focus", event, { item: item } ); 15969 }, 15970 15971 _scrollIntoView: function( item ) { 15972 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; 15973 if ( this._hasScroll() ) { 15974 borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0; 15975 paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0; 15976 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; 15977 scroll = this.activeMenu.scrollTop(); 15978 elementHeight = this.activeMenu.height(); 15979 itemHeight = item.outerHeight(); 15980 15981 if ( offset < 0 ) { 15982 this.activeMenu.scrollTop( scroll + offset ); 15983 } else if ( offset + itemHeight > elementHeight ) { 15984 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); 15985 } 15986 } 15987 }, 15988 15989 blur: function( event, fromFocus ) { 15990 if ( !fromFocus ) { 15991 clearTimeout( this.timer ); 15992 } 15993 15994 if ( !this.active ) { 15995 return; 15996 } 15997 15998 this._removeClass( this.active.children( ".ui-menu-item-wrapper" ), 15999 null, "ui-state-active" ); 16000 16001 this._trigger( "blur", event, { item: this.active } ); 16002 this.active = null; 16003 }, 16004 16005 _startOpening: function( submenu ) { 16006 clearTimeout( this.timer ); 16007 16008 // Don't open if already open fixes a Firefox bug that caused a .5 pixel 16009 // shift in the submenu position when mousing over the caret icon 16010 if ( submenu.attr( "aria-hidden" ) !== "true" ) { 16011 return; 16012 } 16013 16014 this.timer = this._delay( function() { 16015 this._close(); 16016 this._open( submenu ); 16017 }, this.delay ); 16018 }, 16019 16020 _open: function( submenu ) { 16021 var position = $.extend( { 16022 of: this.active 16023 }, this.options.position ); 16024 16025 clearTimeout( this.timer ); 16026 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) 16027 .hide() 16028 .attr( "aria-hidden", "true" ); 16029 16030 submenu 16031 .show() 16032 .removeAttr( "aria-hidden" ) 16033 .attr( "aria-expanded", "true" ) 16034 .position( position ); 16035 }, 16036 16037 collapseAll: function( event, all ) { 16038 clearTimeout( this.timer ); 16039 this.timer = this._delay( function() { 16040 16041 // If we were passed an event, look for the submenu that contains the event 16042 var currentMenu = all ? this.element : 16043 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); 16044 16045 // If we found no valid submenu ancestor, use the main menu to close all 16046 // sub menus anyway 16047 if ( !currentMenu.length ) { 16048 currentMenu = this.element; 16049 } 16050 16051 this._close( currentMenu ); 16052 16053 this.blur( event ); 16054 16055 // Work around active item staying active after menu is blurred 16056 this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" ); 16057 16058 this.activeMenu = currentMenu; 16059 }, all ? 0 : this.delay ); 16060 }, 16061 16062 // With no arguments, closes the currently active menu - if nothing is active 16063 // it closes all menus. If passed an argument, it will search for menus BELOW 16064 _close: function( startMenu ) { 16065 if ( !startMenu ) { 16066 startMenu = this.active ? this.active.parent() : this.element; 16067 } 16068 16069 startMenu.find( ".ui-menu" ) 16070 .hide() 16071 .attr( "aria-hidden", "true" ) 16072 .attr( "aria-expanded", "false" ); 16073 }, 16074 16075 _closeOnDocumentClick: function( event ) { 16076 return !$( event.target ).closest( ".ui-menu" ).length; 16077 }, 16078 16079 _isDivider: function( item ) { 16080 16081 // Match hyphen, em dash, en dash 16082 return !/[^\-\u2014\u2013\s]/.test( item.text() ); 16083 }, 16084 16085 collapse: function( event ) { 16086 var newItem = this.active && 16087 this.active.parent().closest( ".ui-menu-item", this.element ); 16088 if ( newItem && newItem.length ) { 16089 this._close(); 16090 this.focus( event, newItem ); 16091 } 16092 }, 16093 16094 expand: function( event ) { 16095 var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first(); 16096 16097 if ( newItem && newItem.length ) { 16098 this._open( newItem.parent() ); 16099 16100 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 16101 this._delay( function() { 16102 this.focus( event, newItem ); 16103 } ); 16104 } 16105 }, 16106 16107 next: function( event ) { 16108 this._move( "next", "first", event ); 16109 }, 16110 16111 previous: function( event ) { 16112 this._move( "prev", "last", event ); 16113 }, 16114 16115 isFirstItem: function() { 16116 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; 16117 }, 16118 16119 isLastItem: function() { 16120 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; 16121 }, 16122 16123 _menuItems: function( menu ) { 16124 return ( menu || this.element ) 16125 .find( this.options.items ) 16126 .filter( ".ui-menu-item" ); 16127 }, 16128 16129 _move: function( direction, filter, event ) { 16130 var next; 16131 if ( this.active ) { 16132 if ( direction === "first" || direction === "last" ) { 16133 next = this.active 16134 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) 16135 .last(); 16136 } else { 16137 next = this.active 16138 [ direction + "All" ]( ".ui-menu-item" ) 16139 .first(); 16140 } 16141 } 16142 if ( !next || !next.length || !this.active ) { 16143 next = this._menuItems( this.activeMenu )[ filter ](); 16144 } 16145 16146 this.focus( event, next ); 16147 }, 16148 16149 nextPage: function( event ) { 16150 var item, base, height; 16151 16152 if ( !this.active ) { 16153 this.next( event ); 16154 return; 16155 } 16156 if ( this.isLastItem() ) { 16157 return; 16158 } 16159 if ( this._hasScroll() ) { 16160 base = this.active.offset().top; 16161 height = this.element.innerHeight(); 16162 16163 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back. 16164 if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) { 16165 height += this.element[ 0 ].offsetHeight - this.element.outerHeight(); 16166 } 16167 16168 this.active.nextAll( ".ui-menu-item" ).each( function() { 16169 item = $( this ); 16170 return item.offset().top - base - height < 0; 16171 } ); 16172 16173 this.focus( event, item ); 16174 } else { 16175 this.focus( event, this._menuItems( this.activeMenu ) 16176 [ !this.active ? "first" : "last" ]() ); 16177 } 16178 }, 16179 16180 previousPage: function( event ) { 16181 var item, base, height; 16182 if ( !this.active ) { 16183 this.next( event ); 16184 return; 16185 } 16186 if ( this.isFirstItem() ) { 16187 return; 16188 } 16189 if ( this._hasScroll() ) { 16190 base = this.active.offset().top; 16191 height = this.element.innerHeight(); 16192 16193 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back. 16194 if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) { 16195 height += this.element[ 0 ].offsetHeight - this.element.outerHeight(); 16196 } 16197 16198 this.active.prevAll( ".ui-menu-item" ).each( function() { 16199 item = $( this ); 16200 return item.offset().top - base + height > 0; 16201 } ); 16202 16203 this.focus( event, item ); 16204 } else { 16205 this.focus( event, this._menuItems( this.activeMenu ).first() ); 16206 } 16207 }, 16208 16209 _hasScroll: function() { 16210 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); 16211 }, 16212 16213 select: function( event ) { 16214 16215 // TODO: It should never be possible to not have an active item at this 16216 // point, but the tests don't trigger mouseenter before click. 16217 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); 16218 var ui = { item: this.active }; 16219 if ( !this.active.has( ".ui-menu" ).length ) { 16220 this.collapseAll( event, true ); 16221 } 16222 this._trigger( "select", event, ui ); 16223 }, 16224 16225 _filterMenuItems: function( character ) { 16226 var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ), 16227 regex = new RegExp( "^" + escapedCharacter, "i" ); 16228 16229 return this.activeMenu 16230 .find( this.options.items ) 16231 16232 // Only match on items, not dividers or other content (#10571) 16233 .filter( ".ui-menu-item" ) 16234 .filter( function() { 16235 return regex.test( 16236 String.prototype.trim.call( 16237 $( this ).children( ".ui-menu-item-wrapper" ).text() ) ); 16238 } ); 16239 } 16240} ); 16241 16242 16243/*! 16244 * jQuery UI Autocomplete 1.14.1 16245 * https://jqueryui.com 16246 * 16247 * Copyright OpenJS Foundation and other contributors 16248 * Released under the MIT license. 16249 * https://jquery.org/license 16250 */ 16251 16252//>>label: Autocomplete 16253//>>group: Widgets 16254//>>description: Lists suggested words as the user is typing. 16255//>>docs: https://api.jqueryui.com/autocomplete/ 16256//>>demos: https://jqueryui.com/autocomplete/ 16257//>>css.structure: ../../themes/base/core.css 16258//>>css.structure: ../../themes/base/autocomplete.css 16259//>>css.theme: ../../themes/base/theme.css 16260 16261 16262$.widget( "ui.autocomplete", { 16263 version: "1.14.1", 16264 defaultElement: "<input>", 16265 options: { 16266 appendTo: null, 16267 autoFocus: false, 16268 delay: 300, 16269 minLength: 1, 16270 position: { 16271 my: "left top", 16272 at: "left bottom", 16273 collision: "none" 16274 }, 16275 source: null, 16276 16277 // Callbacks 16278 change: null, 16279 close: null, 16280 focus: null, 16281 open: null, 16282 response: null, 16283 search: null, 16284 select: null 16285 }, 16286 16287 requestIndex: 0, 16288 pending: 0, 16289 liveRegionTimer: null, 16290 16291 _create: function() { 16292 16293 // Some browsers only repeat keydown events, not keypress events, 16294 // so we use the suppressKeyPress flag to determine if we've already 16295 // handled the keydown event. #7269 16296 // Unfortunately the code for & in keypress is the same as the up arrow, 16297 // so we use the suppressKeyPressRepeat flag to avoid handling keypress 16298 // events when we know the keydown event was used to modify the 16299 // search term. #7799 16300 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, 16301 nodeName = this.element[ 0 ].nodeName.toLowerCase(), 16302 isTextarea = nodeName === "textarea", 16303 isInput = nodeName === "input"; 16304 16305 // Textareas are always multi-line 16306 // Inputs are always single-line, even if inside a contentEditable element 16307 // All other element types are determined by whether they're contentEditable 16308 this.isMultiLine = isTextarea || 16309 !isInput && this.element.prop( "contentEditable" ) === "true"; 16310 16311 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; 16312 this.isNewMenu = true; 16313 16314 this._addClass( "ui-autocomplete-input" ); 16315 this.element.attr( "autocomplete", "off" ); 16316 16317 this._on( this.element, { 16318 keydown: function( event ) { 16319 if ( this.element.prop( "readOnly" ) ) { 16320 suppressKeyPress = true; 16321 suppressInput = true; 16322 suppressKeyPressRepeat = true; 16323 return; 16324 } 16325 16326 suppressKeyPress = false; 16327 suppressInput = false; 16328 suppressKeyPressRepeat = false; 16329 var keyCode = $.ui.keyCode; 16330 switch ( event.keyCode ) { 16331 case keyCode.PAGE_UP: 16332 suppressKeyPress = true; 16333 this._move( "previousPage", event ); 16334 break; 16335 case keyCode.PAGE_DOWN: 16336 suppressKeyPress = true; 16337 this._move( "nextPage", event ); 16338 break; 16339 case keyCode.UP: 16340 suppressKeyPress = true; 16341 this._keyEvent( "previous", event ); 16342 break; 16343 case keyCode.DOWN: 16344 suppressKeyPress = true; 16345 this._keyEvent( "next", event ); 16346 break; 16347 case keyCode.ENTER: 16348 16349 // when menu is open and has focus 16350 if ( this.menu.active ) { 16351 16352 // #6055 - Opera still allows the keypress to occur 16353 // which causes forms to submit 16354 suppressKeyPress = true; 16355 event.preventDefault(); 16356 this.menu.select( event ); 16357 } 16358 break; 16359 case keyCode.TAB: 16360 if ( this.menu.active ) { 16361 this.menu.select( event ); 16362 } 16363 break; 16364 case keyCode.ESCAPE: 16365 if ( this.menu.element.is( ":visible" ) ) { 16366 if ( !this.isMultiLine ) { 16367 this._value( this.term ); 16368 } 16369 this.close( event ); 16370 16371 // Different browsers have different default behavior for escape 16372 // Single press can mean undo or clear 16373 event.preventDefault(); 16374 } 16375 break; 16376 default: 16377 suppressKeyPressRepeat = true; 16378 16379 // search timeout should be triggered before the input value is changed 16380 this._searchTimeout( event ); 16381 break; 16382 } 16383 }, 16384 keypress: function( event ) { 16385 if ( suppressKeyPress ) { 16386 suppressKeyPress = false; 16387 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 16388 event.preventDefault(); 16389 } 16390 return; 16391 } 16392 if ( suppressKeyPressRepeat ) { 16393 return; 16394 } 16395 16396 // Replicate some key handlers to allow them to repeat in Firefox and Opera 16397 var keyCode = $.ui.keyCode; 16398 switch ( event.keyCode ) { 16399 case keyCode.PAGE_UP: 16400 this._move( "previousPage", event ); 16401 break; 16402 case keyCode.PAGE_DOWN: 16403 this._move( "nextPage", event ); 16404 break; 16405 case keyCode.UP: 16406 this._keyEvent( "previous", event ); 16407 break; 16408 case keyCode.DOWN: 16409 this._keyEvent( "next", event ); 16410 break; 16411 } 16412 }, 16413 input: function( event ) { 16414 if ( suppressInput ) { 16415 suppressInput = false; 16416 event.preventDefault(); 16417 return; 16418 } 16419 this._searchTimeout( event ); 16420 }, 16421 focus: function() { 16422 this.selectedItem = null; 16423 this.previous = this._value(); 16424 }, 16425 blur: function( event ) { 16426 clearTimeout( this.searching ); 16427 this.close( event ); 16428 this._change( event ); 16429 } 16430 } ); 16431 16432 this._initSource(); 16433 this.menu = $( "<ul>" ) 16434 .appendTo( this._appendTo() ) 16435 .menu( { 16436 16437 // disable ARIA support, the live region takes care of that 16438 role: null 16439 } ) 16440 .hide() 16441 .menu( "instance" ); 16442 16443 this._addClass( this.menu.element, "ui-autocomplete", "ui-front" ); 16444 this._on( this.menu.element, { 16445 mousedown: function( event ) { 16446 16447 // Prevent moving focus out of the text field 16448 event.preventDefault(); 16449 }, 16450 menufocus: function( event, ui ) { 16451 var label, item; 16452 16453 // Support: Firefox 16454 // Prevent accidental activation of menu items in Firefox (#7024 #9118) 16455 if ( this.isNewMenu ) { 16456 this.isNewMenu = false; 16457 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { 16458 this.menu.blur(); 16459 16460 this.document.one( "mousemove", function() { 16461 $( event.target ).trigger( event.originalEvent ); 16462 } ); 16463 16464 return; 16465 } 16466 } 16467 16468 item = ui.item.data( "ui-autocomplete-item" ); 16469 if ( false !== this._trigger( "focus", event, { item: item } ) ) { 16470 16471 // use value to match what will end up in the input, if it was a key event 16472 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { 16473 this._value( item.value ); 16474 } 16475 } 16476 16477 // Announce the value in the liveRegion 16478 label = ui.item.attr( "aria-label" ) || item.value; 16479 if ( label && String.prototype.trim.call( label ).length ) { 16480 clearTimeout( this.liveRegionTimer ); 16481 this.liveRegionTimer = this._delay( function() { 16482 this.liveRegion.html( $( "<div>" ).text( label ) ); 16483 }, 100 ); 16484 } 16485 }, 16486 menuselect: function( event, ui ) { 16487 var item = ui.item.data( "ui-autocomplete-item" ), 16488 previous = this.previous; 16489 16490 // Only trigger when focus was lost (click on menu) 16491 if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) { 16492 this.element.trigger( "focus" ); 16493 this.previous = previous; 16494 } 16495 16496 if ( false !== this._trigger( "select", event, { item: item } ) ) { 16497 this._value( item.value ); 16498 } 16499 16500 // reset the term after the select event 16501 // this allows custom select handling to work properly 16502 this.term = this._value(); 16503 16504 this.close( event ); 16505 this.selectedItem = item; 16506 } 16507 } ); 16508 16509 this.liveRegion = $( "<div>", { 16510 role: "status", 16511 "aria-live": "assertive", 16512 "aria-relevant": "additions" 16513 } ) 16514 .appendTo( this.document[ 0 ].body ); 16515 16516 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" ); 16517 16518 // Turning off autocomplete prevents the browser from remembering the 16519 // value when navigating through history, so we re-enable autocomplete 16520 // if the page is unloaded before the widget is destroyed. #7790 16521 this._on( this.window, { 16522 beforeunload: function() { 16523 this.element.removeAttr( "autocomplete" ); 16524 } 16525 } ); 16526 }, 16527 16528 _destroy: function() { 16529 clearTimeout( this.searching ); 16530 this.element.removeAttr( "autocomplete" ); 16531 this.menu.element.remove(); 16532 this.liveRegion.remove(); 16533 }, 16534 16535 _setOption: function( key, value ) { 16536 this._super( key, value ); 16537 if ( key === "source" ) { 16538 this._initSource(); 16539 } 16540 if ( key === "appendTo" ) { 16541 this.menu.element.appendTo( this._appendTo() ); 16542 } 16543 if ( key === "disabled" && value && this.xhr ) { 16544 this.xhr.abort(); 16545 } 16546 }, 16547 16548 _isEventTargetInWidget: function( event ) { 16549 var menuElement = this.menu.element[ 0 ]; 16550 16551 return event.target === this.element[ 0 ] || 16552 event.target === menuElement || 16553 $.contains( menuElement, event.target ); 16554 }, 16555 16556 _closeOnClickOutside: function( event ) { 16557 if ( !this._isEventTargetInWidget( event ) ) { 16558 this.close(); 16559 } 16560 }, 16561 16562 _appendTo: function() { 16563 var element = this.options.appendTo; 16564 16565 if ( element ) { 16566 element = element.jquery || element.nodeType ? 16567 $( element ) : 16568 this.document.find( element ).eq( 0 ); 16569 } 16570 16571 if ( !element || !element[ 0 ] ) { 16572 element = this.element.closest( ".ui-front, dialog" ); 16573 } 16574 16575 if ( !element.length ) { 16576 element = this.document[ 0 ].body; 16577 } 16578 16579 return element; 16580 }, 16581 16582 _initSource: function() { 16583 var array, url, 16584 that = this; 16585 if ( Array.isArray( this.options.source ) ) { 16586 array = this.options.source; 16587 this.source = function( request, response ) { 16588 response( $.ui.autocomplete.filter( array, request.term ) ); 16589 }; 16590 } else if ( typeof this.options.source === "string" ) { 16591 url = this.options.source; 16592 this.source = function( request, response ) { 16593 if ( that.xhr ) { 16594 that.xhr.abort(); 16595 } 16596 that.xhr = $.ajax( { 16597 url: url, 16598 data: request, 16599 dataType: "json", 16600 success: function( data ) { 16601 response( data ); 16602 }, 16603 error: function() { 16604 response( [] ); 16605 } 16606 } ); 16607 }; 16608 } else { 16609 this.source = this.options.source; 16610 } 16611 }, 16612 16613 _searchTimeout: function( event ) { 16614 clearTimeout( this.searching ); 16615 this.searching = this._delay( function() { 16616 16617 // Search if the value has changed, or if the user retypes the same value (see #7434) 16618 var equalValues = this.term === this._value(), 16619 menuVisible = this.menu.element.is( ":visible" ), 16620 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey; 16621 16622 if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) { 16623 this.selectedItem = null; 16624 this.search( null, event ); 16625 } 16626 }, this.options.delay ); 16627 }, 16628 16629 search: function( value, event ) { 16630 value = value != null ? value : this._value(); 16631 16632 // Always save the actual value, not the one passed as an argument 16633 this.term = this._value(); 16634 16635 if ( value.length < this.options.minLength ) { 16636 return this.close( event ); 16637 } 16638 16639 if ( this._trigger( "search", event ) === false ) { 16640 return; 16641 } 16642 16643 return this._search( value ); 16644 }, 16645 16646 _search: function( value ) { 16647 this.pending++; 16648 this._addClass( "ui-autocomplete-loading" ); 16649 this.cancelSearch = false; 16650 16651 this.source( { term: value }, this._response() ); 16652 }, 16653 16654 _response: function() { 16655 var index = ++this.requestIndex; 16656 16657 return function( content ) { 16658 if ( index === this.requestIndex ) { 16659 this.__response( content ); 16660 } 16661 16662 this.pending--; 16663 if ( !this.pending ) { 16664 this._removeClass( "ui-autocomplete-loading" ); 16665 } 16666 }.bind( this ); 16667 }, 16668 16669 __response: function( content ) { 16670 if ( content ) { 16671 content = this._normalize( content ); 16672 } 16673 this._trigger( "response", null, { content: content } ); 16674 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { 16675 this._suggest( content ); 16676 this._trigger( "open" ); 16677 } else { 16678 16679 // use ._close() instead of .close() so we don't cancel future searches 16680 this._close(); 16681 } 16682 }, 16683 16684 close: function( event ) { 16685 this.cancelSearch = true; 16686 this._close( event ); 16687 }, 16688 16689 _close: function( event ) { 16690 16691 // Remove the handler that closes the menu on outside clicks 16692 this._off( this.document, "mousedown" ); 16693 16694 if ( this.menu.element.is( ":visible" ) ) { 16695 this.menu.element.hide(); 16696 this.menu.blur(); 16697 this.isNewMenu = true; 16698 this._trigger( "close", event ); 16699 } 16700 }, 16701 16702 _change: function( event ) { 16703 if ( this.previous !== this._value() ) { 16704 this._trigger( "change", event, { item: this.selectedItem } ); 16705 } 16706 }, 16707 16708 _normalize: function( items ) { 16709 16710 // assume all items have the right format when the first item is complete 16711 if ( items.length && items[ 0 ].label && items[ 0 ].value ) { 16712 return items; 16713 } 16714 return $.map( items, function( item ) { 16715 if ( typeof item === "string" ) { 16716 return { 16717 label: item, 16718 value: item 16719 }; 16720 } 16721 return $.extend( {}, item, { 16722 label: item.label || item.value, 16723 value: item.value || item.label 16724 } ); 16725 } ); 16726 }, 16727 16728 _suggest: function( items ) { 16729 var ul = this.menu.element.empty(); 16730 this._renderMenu( ul, items ); 16731 this.isNewMenu = true; 16732 this.menu.refresh(); 16733 16734 // Size and position menu 16735 ul.show(); 16736 this._resizeMenu(); 16737 ul.position( $.extend( { 16738 of: this.element 16739 }, this.options.position ) ); 16740 16741 if ( this.options.autoFocus ) { 16742 this.menu.next(); 16743 } 16744 16745 // Listen for interactions outside of the widget (#6642) 16746 this._on( this.document, { 16747 mousedown: "_closeOnClickOutside" 16748 } ); 16749 }, 16750 16751 _resizeMenu: function() { 16752 var ul = this.menu.element; 16753 ul.outerWidth( Math.max( 16754 16755 // Firefox wraps long text (possibly a rounding bug) 16756 // so we add 1px to avoid the wrapping (#7513) 16757 ul.width( "" ).outerWidth() + 1, 16758 this.element.outerWidth() 16759 ) ); 16760 }, 16761 16762 _renderMenu: function( ul, items ) { 16763 var that = this; 16764 $.each( items, function( index, item ) { 16765 that._renderItemData( ul, item ); 16766 } ); 16767 }, 16768 16769 _renderItemData: function( ul, item ) { 16770 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); 16771 }, 16772 16773 _renderItem: function( ul, item ) { 16774 return $( "<li>" ) 16775 .append( $( "<div>" ).text( item.label ) ) 16776 .appendTo( ul ); 16777 }, 16778 16779 _move: function( direction, event ) { 16780 if ( !this.menu.element.is( ":visible" ) ) { 16781 this.search( null, event ); 16782 return; 16783 } 16784 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || 16785 this.menu.isLastItem() && /^next/.test( direction ) ) { 16786 16787 if ( !this.isMultiLine ) { 16788 this._value( this.term ); 16789 } 16790 16791 this.menu.blur(); 16792 return; 16793 } 16794 this.menu[ direction ]( event ); 16795 }, 16796 16797 widget: function() { 16798 return this.menu.element; 16799 }, 16800 16801 _value: function() { 16802 return this.valueMethod.apply( this.element, arguments ); 16803 }, 16804 16805 _keyEvent: function( keyEvent, event ) { 16806 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 16807 this._move( keyEvent, event ); 16808 16809 // Prevents moving cursor to beginning/end of the text field in some browsers 16810 event.preventDefault(); 16811 } 16812 } 16813} ); 16814 16815$.extend( $.ui.autocomplete, { 16816 escapeRegex: function( value ) { 16817 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); 16818 }, 16819 filter: function( array, term ) { 16820 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" ); 16821 return $.grep( array, function( value ) { 16822 return matcher.test( value.label || value.value || value ); 16823 } ); 16824 } 16825} ); 16826 16827// Live region extension, adding a `messages` option 16828// NOTE: This is an experimental API. We are still investigating 16829// a full solution for string manipulation and internationalization. 16830$.widget( "ui.autocomplete", $.ui.autocomplete, { 16831 options: { 16832 messages: { 16833 noResults: "No search results.", 16834 results: function( amount ) { 16835 return amount + ( amount > 1 ? " results are" : " result is" ) + 16836 " available, use up and down arrow keys to navigate."; 16837 } 16838 } 16839 }, 16840 16841 __response: function( content ) { 16842 var message; 16843 this._superApply( arguments ); 16844 if ( this.options.disabled || this.cancelSearch ) { 16845 return; 16846 } 16847 if ( content && content.length ) { 16848 message = this.options.messages.results( content.length ); 16849 } else { 16850 message = this.options.messages.noResults; 16851 } 16852 clearTimeout( this.liveRegionTimer ); 16853 this.liveRegionTimer = this._delay( function() { 16854 this.liveRegion.html( $( "<div>" ).text( message ) ); 16855 }, 100 ); 16856 } 16857} ); 16858 16859var widgetsAutocomplete = $.ui.autocomplete; 16860 16861 16862/*! 16863 * jQuery UI Controlgroup 1.14.1 16864 * https://jqueryui.com 16865 * 16866 * Copyright OpenJS Foundation and other contributors 16867 * Released under the MIT license. 16868 * https://jquery.org/license 16869 */ 16870 16871//>>label: Controlgroup 16872//>>group: Widgets 16873//>>description: Visually groups form control widgets 16874//>>docs: https://api.jqueryui.com/controlgroup/ 16875//>>demos: https://jqueryui.com/controlgroup/ 16876//>>css.structure: ../../themes/base/core.css 16877//>>css.structure: ../../themes/base/controlgroup.css 16878//>>css.theme: ../../themes/base/theme.css 16879 16880 16881var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g; 16882 16883var widgetsControlgroup = $.widget( "ui.controlgroup", { 16884 version: "1.14.1", 16885 defaultElement: "<div>", 16886 options: { 16887 direction: "horizontal", 16888 disabled: null, 16889 onlyVisible: true, 16890 items: { 16891 "button": "input[type=button], input[type=submit], input[type=reset], button, a", 16892 "controlgroupLabel": ".ui-controlgroup-label", 16893 "checkboxradio": "input[type='checkbox'], input[type='radio']", 16894 "selectmenu": "select", 16895 "spinner": ".ui-spinner-input" 16896 } 16897 }, 16898 16899 _create: function() { 16900 this._enhance(); 16901 }, 16902 16903 // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation 16904 _enhance: function() { 16905 this.element.attr( "role", "toolbar" ); 16906 this.refresh(); 16907 }, 16908 16909 _destroy: function() { 16910 this._callChildMethod( "destroy" ); 16911 this.childWidgets.removeData( "ui-controlgroup-data" ); 16912 this.element.removeAttr( "role" ); 16913 if ( this.options.items.controlgroupLabel ) { 16914 this.element 16915 .find( this.options.items.controlgroupLabel ) 16916 .find( ".ui-controlgroup-label-contents" ) 16917 .contents().unwrap(); 16918 } 16919 }, 16920 16921 _initWidgets: function() { 16922 var that = this, 16923 childWidgets = []; 16924 16925 // First we iterate over each of the items options 16926 $.each( this.options.items, function( widget, selector ) { 16927 var labels; 16928 var options = {}; 16929 16930 // Make sure the widget has a selector set 16931 if ( !selector ) { 16932 return; 16933 } 16934 16935 if ( widget === "controlgroupLabel" ) { 16936 labels = that.element.find( selector ); 16937 labels.each( function() { 16938 var element = $( this ); 16939 16940 if ( element.children( ".ui-controlgroup-label-contents" ).length ) { 16941 return; 16942 } 16943 element.contents() 16944 .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" ); 16945 } ); 16946 that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" ); 16947 childWidgets = childWidgets.concat( labels.get() ); 16948 return; 16949 } 16950 16951 // Make sure the widget actually exists 16952 if ( !$.fn[ widget ] ) { 16953 return; 16954 } 16955 16956 // We assume everything is in the middle to start because we can't determine 16957 // first / last elements until all enhancments are done. 16958 if ( that[ "_" + widget + "Options" ] ) { 16959 options = that[ "_" + widget + "Options" ]( "middle" ); 16960 } else { 16961 options = { classes: {} }; 16962 } 16963 16964 // Find instances of this widget inside controlgroup and init them 16965 that.element 16966 .find( selector ) 16967 .each( function() { 16968 var element = $( this ); 16969 var instance = element[ widget ]( "instance" ); 16970 16971 // We need to clone the default options for this type of widget to avoid 16972 // polluting the variable options which has a wider scope than a single widget. 16973 var instanceOptions = $.widget.extend( {}, options ); 16974 16975 // If the button is the child of a spinner ignore it 16976 // TODO: Find a more generic solution 16977 if ( widget === "button" && element.parent( ".ui-spinner" ).length ) { 16978 return; 16979 } 16980 16981 // Create the widget if it doesn't exist 16982 if ( !instance ) { 16983 instance = element[ widget ]()[ widget ]( "instance" ); 16984 } 16985 if ( instance ) { 16986 instanceOptions.classes = 16987 that._resolveClassesValues( instanceOptions.classes, instance ); 16988 } 16989 element[ widget ]( instanceOptions ); 16990 16991 // Store an instance of the controlgroup to be able to reference 16992 // from the outermost element for changing options and refresh 16993 var widgetElement = element[ widget ]( "widget" ); 16994 $.data( widgetElement[ 0 ], "ui-controlgroup-data", 16995 instance ? instance : element[ widget ]( "instance" ) ); 16996 16997 childWidgets.push( widgetElement[ 0 ] ); 16998 } ); 16999 } ); 17000 17001 this.childWidgets = $( $.uniqueSort( childWidgets ) ); 17002 this._addClass( this.childWidgets, "ui-controlgroup-item" ); 17003 }, 17004 17005 _callChildMethod: function( method ) { 17006 this.childWidgets.each( function() { 17007 var element = $( this ), 17008 data = element.data( "ui-controlgroup-data" ); 17009 if ( data && data[ method ] ) { 17010 data[ method ](); 17011 } 17012 } ); 17013 }, 17014 17015 _updateCornerClass: function( element, position ) { 17016 var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all"; 17017 var add = this._buildSimpleOptions( position, "label" ).classes.label; 17018 17019 this._removeClass( element, null, remove ); 17020 this._addClass( element, null, add ); 17021 }, 17022 17023 _buildSimpleOptions: function( position, key ) { 17024 var direction = this.options.direction === "vertical"; 17025 var result = { 17026 classes: {} 17027 }; 17028 result.classes[ key ] = { 17029 "middle": "", 17030 "first": "ui-corner-" + ( direction ? "top" : "left" ), 17031 "last": "ui-corner-" + ( direction ? "bottom" : "right" ), 17032 "only": "ui-corner-all" 17033 }[ position ]; 17034 17035 return result; 17036 }, 17037 17038 _spinnerOptions: function( position ) { 17039 var options = this._buildSimpleOptions( position, "ui-spinner" ); 17040 17041 options.classes[ "ui-spinner-up" ] = ""; 17042 options.classes[ "ui-spinner-down" ] = ""; 17043 17044 return options; 17045 }, 17046 17047 _buttonOptions: function( position ) { 17048 return this._buildSimpleOptions( position, "ui-button" ); 17049 }, 17050 17051 _checkboxradioOptions: function( position ) { 17052 return this._buildSimpleOptions( position, "ui-checkboxradio-label" ); 17053 }, 17054 17055 _selectmenuOptions: function( position ) { 17056 var direction = this.options.direction === "vertical"; 17057 return { 17058 width: direction ? "auto" : false, 17059 classes: { 17060 middle: { 17061 "ui-selectmenu-button-open": "", 17062 "ui-selectmenu-button-closed": "" 17063 }, 17064 first: { 17065 "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ), 17066 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" ) 17067 }, 17068 last: { 17069 "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr", 17070 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" ) 17071 }, 17072 only: { 17073 "ui-selectmenu-button-open": "ui-corner-top", 17074 "ui-selectmenu-button-closed": "ui-corner-all" 17075 } 17076 17077 }[ position ] 17078 }; 17079 }, 17080 17081 _resolveClassesValues: function( classes, instance ) { 17082 var result = {}; 17083 $.each( classes, function( key ) { 17084 var current = instance.options.classes[ key ] || ""; 17085 current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) ); 17086 result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " ); 17087 } ); 17088 return result; 17089 }, 17090 17091 _setOption: function( key, value ) { 17092 if ( key === "direction" ) { 17093 this._removeClass( "ui-controlgroup-" + this.options.direction ); 17094 } 17095 17096 this._super( key, value ); 17097 if ( key === "disabled" ) { 17098 this._callChildMethod( value ? "disable" : "enable" ); 17099 return; 17100 } 17101 17102 this.refresh(); 17103 }, 17104 17105 refresh: function() { 17106 var children, 17107 that = this; 17108 17109 this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction ); 17110 17111 if ( this.options.direction === "horizontal" ) { 17112 this._addClass( null, "ui-helper-clearfix" ); 17113 } 17114 this._initWidgets(); 17115 17116 children = this.childWidgets; 17117 17118 // We filter here because we need to track all childWidgets not just the visible ones 17119 if ( this.options.onlyVisible ) { 17120 children = children.filter( ":visible" ); 17121 } 17122 17123 if ( children.length ) { 17124 17125 // We do this last because we need to make sure all enhancment is done 17126 // before determining first and last 17127 $.each( [ "first", "last" ], function( index, value ) { 17128 var instance = children[ value ]().data( "ui-controlgroup-data" ); 17129 17130 if ( instance && that[ "_" + instance.widgetName + "Options" ] ) { 17131 var options = that[ "_" + instance.widgetName + "Options" ]( 17132 children.length === 1 ? "only" : value 17133 ); 17134 options.classes = that._resolveClassesValues( options.classes, instance ); 17135 instance.element[ instance.widgetName ]( options ); 17136 } else { 17137 that._updateCornerClass( children[ value ](), value ); 17138 } 17139 } ); 17140 17141 // Finally call the refresh method on each of the child widgets. 17142 this._callChildMethod( "refresh" ); 17143 } 17144 } 17145} ); 17146 17147/*! 17148 * jQuery UI Checkboxradio 1.14.1 17149 * https://jqueryui.com 17150 * 17151 * Copyright OpenJS Foundation and other contributors 17152 * Released under the MIT license. 17153 * https://jquery.org/license 17154 */ 17155 17156//>>label: Checkboxradio 17157//>>group: Widgets 17158//>>description: Enhances a form with multiple themeable checkboxes or radio buttons. 17159//>>docs: https://api.jqueryui.com/checkboxradio/ 17160//>>demos: https://jqueryui.com/checkboxradio/ 17161//>>css.structure: ../../themes/base/core.css 17162//>>css.structure: ../../themes/base/button.css 17163//>>css.structure: ../../themes/base/checkboxradio.css 17164//>>css.theme: ../../themes/base/theme.css 17165 17166 17167$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, { 17168 version: "1.14.1", 17169 options: { 17170 disabled: null, 17171 label: null, 17172 icon: true, 17173 classes: { 17174 "ui-checkboxradio-label": "ui-corner-all", 17175 "ui-checkboxradio-icon": "ui-corner-all" 17176 } 17177 }, 17178 17179 _getCreateOptions: function() { 17180 var disabled, labels, labelContents; 17181 var options = this._super() || {}; 17182 17183 // We read the type here, because it makes more sense to throw a element type error first, 17184 // rather then the error for lack of a label. Often if its the wrong type, it 17185 // won't have a label (e.g. calling on a div, btn, etc) 17186 this._readType(); 17187 17188 labels = this.element.labels(); 17189 17190 // If there are multiple labels, use the last one 17191 this.label = $( labels[ labels.length - 1 ] ); 17192 if ( !this.label.length ) { 17193 $.error( "No label found for checkboxradio widget" ); 17194 } 17195 17196 this.originalLabel = ""; 17197 17198 // We need to get the label text but this may also need to make sure it does not contain the 17199 // input itself. 17200 // The label contents could be text, html, or a mix. We wrap all elements 17201 // and read the wrapper's `innerHTML` to get a string representation of 17202 // the label, without the input as part of it. 17203 labelContents = this.label.contents().not( this.element[ 0 ] ); 17204 17205 if ( labelContents.length ) { 17206 this.originalLabel += labelContents 17207 .clone() 17208 .wrapAll( "<div></div>" ) 17209 .parent() 17210 .html(); 17211 } 17212 17213 // Set the label option if we found label text 17214 if ( this.originalLabel ) { 17215 options.label = this.originalLabel; 17216 } 17217 17218 disabled = this.element[ 0 ].disabled; 17219 if ( disabled != null ) { 17220 options.disabled = disabled; 17221 } 17222 return options; 17223 }, 17224 17225 _create: function() { 17226 var checked = this.element[ 0 ].checked; 17227 17228 this._bindFormResetHandler(); 17229 17230 if ( this.options.disabled == null ) { 17231 this.options.disabled = this.element[ 0 ].disabled; 17232 } 17233 17234 this._setOption( "disabled", this.options.disabled ); 17235 this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" ); 17236 this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" ); 17237 17238 if ( this.type === "radio" ) { 17239 this._addClass( this.label, "ui-checkboxradio-radio-label" ); 17240 } 17241 17242 if ( this.options.label && this.options.label !== this.originalLabel ) { 17243 this._updateLabel(); 17244 } else if ( this.originalLabel ) { 17245 this.options.label = this.originalLabel; 17246 } 17247 17248 this._enhance(); 17249 17250 if ( checked ) { 17251 this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" ); 17252 } 17253 17254 this._on( { 17255 change: "_toggleClasses", 17256 focus: function() { 17257 this._addClass( this.label, null, "ui-state-focus ui-visual-focus" ); 17258 }, 17259 blur: function() { 17260 this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" ); 17261 } 17262 } ); 17263 }, 17264 17265 _readType: function() { 17266 var nodeName = this.element[ 0 ].nodeName.toLowerCase(); 17267 this.type = this.element[ 0 ].type; 17268 if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) { 17269 $.error( "Can't create checkboxradio on element.nodeName=" + nodeName + 17270 " and element.type=" + this.type ); 17271 } 17272 }, 17273 17274 // Support jQuery Mobile enhanced option 17275 _enhance: function() { 17276 this._updateIcon( this.element[ 0 ].checked ); 17277 }, 17278 17279 widget: function() { 17280 return this.label; 17281 }, 17282 17283 _getRadioGroup: function() { 17284 var group; 17285 var name = this.element[ 0 ].name; 17286 var nameSelector = "input[name='" + CSS.escape( name ) + "']"; 17287 17288 if ( !name ) { 17289 return $( [] ); 17290 } 17291 17292 if ( this.form.length ) { 17293 group = $( this.form[ 0 ].elements ).filter( nameSelector ); 17294 } else { 17295 17296 // Not inside a form, check all inputs that also are not inside a form 17297 group = $( nameSelector ).filter( function() { 17298 return $( $( this ).prop( "form" ) ).length === 0; 17299 } ); 17300 } 17301 17302 return group.not( this.element ); 17303 }, 17304 17305 _toggleClasses: function() { 17306 var checked = this.element[ 0 ].checked; 17307 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); 17308 17309 if ( this.options.icon && this.type === "checkbox" ) { 17310 this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked ) 17311 ._toggleClass( this.icon, null, "ui-icon-blank", !checked ); 17312 } 17313 17314 if ( this.type === "radio" ) { 17315 this._getRadioGroup() 17316 .each( function() { 17317 var instance = $( this ).checkboxradio( "instance" ); 17318 17319 if ( instance ) { 17320 instance._removeClass( instance.label, 17321 "ui-checkboxradio-checked", "ui-state-active" ); 17322 } 17323 } ); 17324 } 17325 }, 17326 17327 _destroy: function() { 17328 this._unbindFormResetHandler(); 17329 17330 if ( this.icon ) { 17331 this.icon.remove(); 17332 this.iconSpace.remove(); 17333 } 17334 }, 17335 17336 _setOption: function( key, value ) { 17337 17338 // We don't allow the value to be set to nothing 17339 if ( key === "label" && !value ) { 17340 return; 17341 } 17342 17343 this._super( key, value ); 17344 17345 if ( key === "disabled" ) { 17346 this._toggleClass( this.label, null, "ui-state-disabled", value ); 17347 this.element[ 0 ].disabled = value; 17348 17349 // Don't refresh when setting disabled 17350 return; 17351 } 17352 this.refresh(); 17353 }, 17354 17355 _updateIcon: function( checked ) { 17356 var toAdd = "ui-icon ui-icon-background "; 17357 17358 if ( this.options.icon ) { 17359 if ( !this.icon ) { 17360 this.icon = $( "<span>" ); 17361 this.iconSpace = $( "<span> </span>" ); 17362 this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" ); 17363 } 17364 17365 if ( this.type === "checkbox" ) { 17366 toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank"; 17367 this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" ); 17368 } else { 17369 toAdd += "ui-icon-blank"; 17370 } 17371 this._addClass( this.icon, "ui-checkboxradio-icon", toAdd ); 17372 if ( !checked ) { 17373 this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" ); 17374 } 17375 this.icon.prependTo( this.label ).after( this.iconSpace ); 17376 } else if ( this.icon !== undefined ) { 17377 this.icon.remove(); 17378 this.iconSpace.remove(); 17379 delete this.icon; 17380 } 17381 }, 17382 17383 _updateLabel: function() { 17384 17385 // Remove the contents of the label ( minus the icon, icon space, and input ) 17386 var contents = this.label.contents().not( this.element[ 0 ] ); 17387 if ( this.icon ) { 17388 contents = contents.not( this.icon[ 0 ] ); 17389 } 17390 if ( this.iconSpace ) { 17391 contents = contents.not( this.iconSpace[ 0 ] ); 17392 } 17393 contents.remove(); 17394 17395 this.label.append( this.options.label ); 17396 }, 17397 17398 refresh: function() { 17399 var checked = this.element[ 0 ].checked, 17400 isDisabled = this.element[ 0 ].disabled; 17401 17402 this._updateIcon( checked ); 17403 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); 17404 if ( this.options.label !== null ) { 17405 this._updateLabel(); 17406 } 17407 17408 if ( isDisabled !== this.options.disabled ) { 17409 this._setOptions( { "disabled": isDisabled } ); 17410 } 17411 } 17412 17413} ] ); 17414 17415var widgetsCheckboxradio = $.ui.checkboxradio; 17416 17417 17418/*! 17419 * jQuery UI Button 1.14.1 17420 * https://jqueryui.com 17421 * 17422 * Copyright OpenJS Foundation and other contributors 17423 * Released under the MIT license. 17424 * https://jquery.org/license 17425 */ 17426 17427//>>label: Button 17428//>>group: Widgets 17429//>>description: Enhances a form with themeable buttons. 17430//>>docs: https://api.jqueryui.com/button/ 17431//>>demos: https://jqueryui.com/button/ 17432//>>css.structure: ../../themes/base/core.css 17433//>>css.structure: ../../themes/base/button.css 17434//>>css.theme: ../../themes/base/theme.css 17435 17436 17437$.widget( "ui.button", { 17438 version: "1.14.1", 17439 defaultElement: "<button>", 17440 options: { 17441 classes: { 17442 "ui-button": "ui-corner-all" 17443 }, 17444 disabled: null, 17445 icon: null, 17446 iconPosition: "beginning", 17447 label: null, 17448 showLabel: true 17449 }, 17450 17451 _getCreateOptions: function() { 17452 var disabled, 17453 17454 // This is to support cases like in jQuery Mobile where the base widget does have 17455 // an implementation of _getCreateOptions 17456 options = this._super() || {}; 17457 17458 this.isInput = this.element.is( "input" ); 17459 17460 disabled = this.element[ 0 ].disabled; 17461 if ( disabled != null ) { 17462 options.disabled = disabled; 17463 } 17464 17465 this.originalLabel = this.isInput ? this.element.val() : this.element.html(); 17466 if ( this.originalLabel ) { 17467 options.label = this.originalLabel; 17468 } 17469 17470 return options; 17471 }, 17472 17473 _create: function() { 17474 if ( !this.option.showLabel & !this.options.icon ) { 17475 this.options.showLabel = true; 17476 } 17477 17478 // We have to check the option again here even though we did in _getCreateOptions, 17479 // because null may have been passed on init which would override what was set in 17480 // _getCreateOptions 17481 if ( this.options.disabled == null ) { 17482 this.options.disabled = this.element[ 0 ].disabled || false; 17483 } 17484 17485 this.hasTitle = !!this.element.attr( "title" ); 17486 17487 // Check to see if the label needs to be set or if its already correct 17488 if ( this.options.label && this.options.label !== this.originalLabel ) { 17489 if ( this.isInput ) { 17490 this.element.val( this.options.label ); 17491 } else { 17492 this.element.html( this.options.label ); 17493 } 17494 } 17495 this._addClass( "ui-button", "ui-widget" ); 17496 this._setOption( "disabled", this.options.disabled ); 17497 this._enhance(); 17498 17499 if ( this.element.is( "a" ) ) { 17500 this._on( { 17501 "keyup": function( event ) { 17502 if ( event.keyCode === $.ui.keyCode.SPACE ) { 17503 event.preventDefault(); 17504 17505 // If a native click is available use it, so we 17506 // actually cause navigation. Otherwise, just trigger 17507 // a click event. 17508 if ( this.element[ 0 ].click ) { 17509 this.element[ 0 ].click(); 17510 } else { 17511 this.element.trigger( "click" ); 17512 } 17513 } 17514 } 17515 } ); 17516 } 17517 }, 17518 17519 _enhance: function() { 17520 if ( !this.element.is( "button" ) ) { 17521 this.element.attr( "role", "button" ); 17522 } 17523 17524 if ( this.options.icon ) { 17525 this._updateIcon( "icon", this.options.icon ); 17526 this._updateTooltip(); 17527 } 17528 }, 17529 17530 _updateTooltip: function() { 17531 this.title = this.element.attr( "title" ); 17532 17533 if ( !this.options.showLabel && !this.title ) { 17534 this.element.attr( "title", this.options.label ); 17535 } 17536 }, 17537 17538 _updateIcon: function( option, value ) { 17539 var icon = option !== "iconPosition", 17540 position = icon ? this.options.iconPosition : value, 17541 displayBlock = position === "top" || position === "bottom"; 17542 17543 // Create icon 17544 if ( !this.icon ) { 17545 this.icon = $( "<span>" ); 17546 17547 this._addClass( this.icon, "ui-button-icon", "ui-icon" ); 17548 17549 if ( !this.options.showLabel ) { 17550 this._addClass( "ui-button-icon-only" ); 17551 } 17552 } else if ( icon ) { 17553 17554 // If we are updating the icon remove the old icon class 17555 this._removeClass( this.icon, null, this.options.icon ); 17556 } 17557 17558 // If we are updating the icon add the new icon class 17559 if ( icon ) { 17560 this._addClass( this.icon, null, value ); 17561 } 17562 17563 this._attachIcon( position ); 17564 17565 // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove 17566 // the iconSpace if there is one. 17567 if ( displayBlock ) { 17568 this._addClass( this.icon, null, "ui-widget-icon-block" ); 17569 if ( this.iconSpace ) { 17570 this.iconSpace.remove(); 17571 } 17572 } else { 17573 17574 // Position is beginning or end so remove the ui-widget-icon-block class and add the 17575 // space if it does not exist 17576 if ( !this.iconSpace ) { 17577 this.iconSpace = $( "<span> </span>" ); 17578 this._addClass( this.iconSpace, "ui-button-icon-space" ); 17579 } 17580 this._removeClass( this.icon, null, "ui-wiget-icon-block" ); 17581 this._attachIconSpace( position ); 17582 } 17583 }, 17584 17585 _destroy: function() { 17586 this.element.removeAttr( "role" ); 17587 17588 if ( this.icon ) { 17589 this.icon.remove(); 17590 } 17591 if ( this.iconSpace ) { 17592 this.iconSpace.remove(); 17593 } 17594 if ( !this.hasTitle ) { 17595 this.element.removeAttr( "title" ); 17596 } 17597 }, 17598 17599 _attachIconSpace: function( iconPosition ) { 17600 this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace ); 17601 }, 17602 17603 _attachIcon: function( iconPosition ) { 17604 this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon ); 17605 }, 17606 17607 _setOptions: function( options ) { 17608 var newShowLabel = options.showLabel === undefined ? 17609 this.options.showLabel : 17610 options.showLabel, 17611 newIcon = options.icon === undefined ? this.options.icon : options.icon; 17612 17613 if ( !newShowLabel && !newIcon ) { 17614 options.showLabel = true; 17615 } 17616 this._super( options ); 17617 }, 17618 17619 _setOption: function( key, value ) { 17620 if ( key === "icon" ) { 17621 if ( value ) { 17622 this._updateIcon( key, value ); 17623 } else if ( this.icon ) { 17624 this.icon.remove(); 17625 if ( this.iconSpace ) { 17626 this.iconSpace.remove(); 17627 } 17628 } 17629 } 17630 17631 if ( key === "iconPosition" ) { 17632 this._updateIcon( key, value ); 17633 } 17634 17635 // Make sure we can't end up with a button that has neither text nor icon 17636 if ( key === "showLabel" ) { 17637 this._toggleClass( "ui-button-icon-only", null, !value ); 17638 this._updateTooltip(); 17639 } 17640 17641 if ( key === "label" ) { 17642 if ( this.isInput ) { 17643 this.element.val( value ); 17644 } else { 17645 17646 // If there is an icon, append it, else nothing then append the value 17647 // this avoids removal of the icon when setting label text 17648 this.element.html( value ); 17649 if ( this.icon ) { 17650 this._attachIcon( this.options.iconPosition ); 17651 this._attachIconSpace( this.options.iconPosition ); 17652 } 17653 } 17654 } 17655 17656 this._super( key, value ); 17657 17658 if ( key === "disabled" ) { 17659 this._toggleClass( null, "ui-state-disabled", value ); 17660 this.element[ 0 ].disabled = value; 17661 if ( value ) { 17662 this.element.trigger( "blur" ); 17663 } 17664 } 17665 }, 17666 17667 refresh: function() { 17668 17669 // Make sure to only check disabled if its an element that supports this otherwise 17670 // check for the disabled class to determine state 17671 var isDisabled = this.element.is( "input, button" ) ? 17672 this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" ); 17673 17674 if ( isDisabled !== this.options.disabled ) { 17675 this._setOptions( { disabled: isDisabled } ); 17676 } 17677 17678 this._updateTooltip(); 17679 } 17680} ); 17681 17682// DEPRECATED 17683if ( $.uiBackCompat === true ) { 17684 17685 // Text and Icons options 17686 $.widget( "ui.button", $.ui.button, { 17687 options: { 17688 text: true, 17689 icons: { 17690 primary: null, 17691 secondary: null 17692 } 17693 }, 17694 17695 _create: function() { 17696 if ( this.options.showLabel && !this.options.text ) { 17697 this.options.showLabel = this.options.text; 17698 } 17699 if ( !this.options.showLabel && this.options.text ) { 17700 this.options.text = this.options.showLabel; 17701 } 17702 if ( !this.options.icon && ( this.options.icons.primary || 17703 this.options.icons.secondary ) ) { 17704 if ( this.options.icons.primary ) { 17705 this.options.icon = this.options.icons.primary; 17706 } else { 17707 this.options.icon = this.options.icons.secondary; 17708 this.options.iconPosition = "end"; 17709 } 17710 } else if ( this.options.icon ) { 17711 this.options.icons.primary = this.options.icon; 17712 } 17713 this._super(); 17714 }, 17715 17716 _setOption: function( key, value ) { 17717 if ( key === "text" ) { 17718 this._super( "showLabel", value ); 17719 return; 17720 } 17721 if ( key === "showLabel" ) { 17722 this.options.text = value; 17723 } 17724 if ( key === "icon" ) { 17725 this.options.icons.primary = value; 17726 } 17727 if ( key === "icons" ) { 17728 if ( value.primary ) { 17729 this._super( "icon", value.primary ); 17730 this._super( "iconPosition", "beginning" ); 17731 } else if ( value.secondary ) { 17732 this._super( "icon", value.secondary ); 17733 this._super( "iconPosition", "end" ); 17734 } 17735 } 17736 this._superApply( arguments ); 17737 } 17738 } ); 17739 17740 $.fn.button = ( function( orig ) { 17741 return function( options ) { 17742 var isMethodCall = typeof options === "string"; 17743 var args = Array.prototype.slice.call( arguments, 1 ); 17744 var returnValue = this; 17745 17746 if ( isMethodCall ) { 17747 17748 // If this is an empty collection, we need to have the instance method 17749 // return undefined instead of the jQuery instance 17750 if ( !this.length && options === "instance" ) { 17751 returnValue = undefined; 17752 } else { 17753 this.each( function() { 17754 var methodValue; 17755 var type = $( this ).attr( "type" ); 17756 var name = type !== "checkbox" && type !== "radio" ? 17757 "button" : 17758 "checkboxradio"; 17759 var instance = $.data( this, "ui-" + name ); 17760 17761 if ( options === "instance" ) { 17762 returnValue = instance; 17763 return false; 17764 } 17765 17766 if ( !instance ) { 17767 return $.error( "cannot call methods on button" + 17768 " prior to initialization; " + 17769 "attempted to call method '" + options + "'" ); 17770 } 17771 17772 if ( typeof instance[ options ] !== "function" || 17773 options.charAt( 0 ) === "_" ) { 17774 return $.error( "no such method '" + options + "' for button" + 17775 " widget instance" ); 17776 } 17777 17778 methodValue = instance[ options ].apply( instance, args ); 17779 17780 if ( methodValue !== instance && methodValue !== undefined ) { 17781 returnValue = methodValue && methodValue.jquery ? 17782 returnValue.pushStack( methodValue.get() ) : 17783 methodValue; 17784 return false; 17785 } 17786 } ); 17787 } 17788 } else { 17789 17790 // Allow multiple hashes to be passed on init 17791 if ( args.length ) { 17792 options = $.widget.extend.apply( null, [ options ].concat( args ) ); 17793 } 17794 17795 this.each( function() { 17796 var type = $( this ).attr( "type" ); 17797 var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio"; 17798 var instance = $.data( this, "ui-" + name ); 17799 17800 if ( instance ) { 17801 instance.option( options || {} ); 17802 if ( instance._init ) { 17803 instance._init(); 17804 } 17805 } else { 17806 if ( name === "button" ) { 17807 orig.call( $( this ), options ); 17808 return; 17809 } 17810 17811 $( this ).checkboxradio( $.extend( { icon: false }, options ) ); 17812 } 17813 } ); 17814 } 17815 17816 return returnValue; 17817 }; 17818 } )( $.fn.button ); 17819 17820 $.fn.buttonset = function() { 17821 if ( !$.ui.controlgroup ) { 17822 $.error( "Controlgroup widget missing" ); 17823 } 17824 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) { 17825 return this.controlgroup.apply( this, 17826 [ arguments[ 0 ], "items.button", arguments[ 2 ] ] ); 17827 } 17828 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) { 17829 return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] ); 17830 } 17831 if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) { 17832 arguments[ 0 ].items = { 17833 button: arguments[ 0 ].items 17834 }; 17835 } 17836 return this.controlgroup.apply( this, arguments ); 17837 }; 17838} 17839 17840var widgetsButton = $.ui.button; 17841 17842 17843/* eslint-disable max-len, camelcase */ 17844/*! 17845 * jQuery UI Datepicker 1.14.1 17846 * https://jqueryui.com 17847 * 17848 * Copyright OpenJS Foundation and other contributors 17849 * Released under the MIT license. 17850 * https://jquery.org/license 17851 */ 17852 17853//>>label: Datepicker 17854//>>group: Widgets 17855//>>description: Displays a calendar from an input or inline for selecting dates. 17856//>>docs: https://api.jqueryui.com/datepicker/ 17857//>>demos: https://jqueryui.com/datepicker/ 17858//>>css.structure: ../../themes/base/core.css 17859//>>css.structure: ../../themes/base/datepicker.css 17860//>>css.theme: ../../themes/base/theme.css 17861 17862 17863$.extend( $.ui, { datepicker: { version: "1.14.1" } } ); 17864 17865var datepicker_instActive; 17866 17867function datepicker_getZindex( elem ) { 17868 var position, value; 17869 while ( elem.length && elem[ 0 ] !== document ) { 17870 17871 // Ignore z-index if position is set to a value where z-index is ignored by the browser 17872 // This makes behavior of this function consistent across browsers 17873 // WebKit always returns auto if the element is positioned 17874 position = elem.css( "position" ); 17875 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 17876 17877 // IE returns 0 when zIndex is not specified 17878 // other browsers return a string 17879 // we ignore the case of nested elements with an explicit value of 0 17880 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 17881 value = parseInt( elem.css( "zIndex" ), 10 ); 17882 if ( !isNaN( value ) && value !== 0 ) { 17883 return value; 17884 } 17885 } 17886 elem = elem.parent(); 17887 } 17888 17889 return 0; 17890} 17891 17892/* Date picker manager. 17893 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 17894 Settings for (groups of) date pickers are maintained in an instance object, 17895 allowing multiple different settings on the same page. */ 17896 17897function Datepicker() { 17898 this._curInst = null; // The current instance in use 17899 this._keyEvent = false; // If the last event was a key event 17900 this._disabledInputs = []; // List of date picker inputs that have been disabled 17901 this._datepickerShowing = false; // True if the popup picker is showing , false if not 17902 this._inDialog = false; // True if showing within a "dialog", false if not 17903 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 17904 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 17905 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 17906 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 17907 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 17908 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 17909 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 17910 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 17911 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 17912 this.regional = []; // Available regional settings, indexed by language code 17913 this.regional[ "" ] = { // Default regional settings 17914 closeText: "Done", // Display text for close link 17915 prevText: "Prev", // Display text for previous month link 17916 nextText: "Next", // Display text for next month link 17917 currentText: "Today", // Display text for current month link 17918 monthNames: [ "January", "February", "March", "April", "May", "June", 17919 "July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting 17920 monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting 17921 dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting 17922 dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting 17923 dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday 17924 weekHeader: "Wk", // Column header for week of the year 17925 dateFormat: "mm/dd/yy", // See format options on parseDate 17926 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 17927 isRTL: false, // True if right-to-left language, false if left-to-right 17928 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 17929 yearSuffix: "", // Additional text to append to the year in the month headers, 17930 selectMonthLabel: "Select month", // Invisible label for month selector 17931 selectYearLabel: "Select year" // Invisible label for year selector 17932 }; 17933 this._defaults = { // Global defaults for all the date picker instances 17934 showOn: "focus", // "focus" for popup on focus, 17935 // "button" for trigger button, or "both" for either 17936 showAnim: "fadeIn", // Name of jQuery animation for popup 17937 showOptions: {}, // Options for enhanced animations 17938 defaultDate: null, // Used when field is blank: actual date, 17939 // +/-number for offset from today, null for today 17940 appendText: "", // Display text following the input box, e.g. showing the format 17941 buttonText: "...", // Text for trigger button 17942 buttonImage: "", // URL for trigger button image 17943 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 17944 hideIfNoPrevNext: false, // True to hide next/previous month links 17945 // if not applicable, false to just disable them 17946 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 17947 gotoCurrent: false, // True if today link goes back to current selection instead 17948 changeMonth: false, // True if month can be selected directly, false if only prev/next 17949 changeYear: false, // True if year can be selected directly, false if only prev/next 17950 yearRange: "c-10:c+10", // Range of years to display in drop-down, 17951 // either relative to today's year (-nn:+nn), relative to currently displayed year 17952 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 17953 showOtherMonths: false, // True to show dates in other months, false to leave blank 17954 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 17955 showWeek: false, // True to show week of the year, false to not show it 17956 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 17957 // takes a Date and returns the number of the week for it 17958 shortYearCutoff: "+10", // Short year values < this are in the current century, 17959 // > this are in the previous century, 17960 // string value starting with "+" for current year + value 17961 minDate: null, // The earliest selectable date, or null for no limit 17962 maxDate: null, // The latest selectable date, or null for no limit 17963 duration: "fast", // Duration of display/closure 17964 beforeShowDay: null, // Function that takes a date and returns an array with 17965 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 17966 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 17967 beforeShow: null, // Function that takes an input field and 17968 // returns a set of custom settings for the date picker 17969 onSelect: null, // Define a callback function when a date is selected 17970 onChangeMonthYear: null, // Define a callback function when the month or year is changed 17971 onClose: null, // Define a callback function when the datepicker is closed 17972 onUpdateDatepicker: null, // Define a callback function when the datepicker is updated 17973 numberOfMonths: 1, // Number of months to show at a time 17974 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 17975 stepMonths: 1, // Number of months to step back/forward 17976 stepBigMonths: 12, // Number of months to step back/forward for the big links 17977 altField: "", // Selector for an alternate field to store selected dates into 17978 altFormat: "", // The date format to use for the alternate field 17979 constrainInput: true, // The input is constrained by the current date format 17980 showButtonPanel: false, // True to show button panel, false to not show it 17981 autoSize: false, // True to size the input for the date format, false to leave as is 17982 disabled: false // The initial disabled state 17983 }; 17984 $.extend( this._defaults, this.regional[ "" ] ); 17985 this.regional.en = $.extend( true, {}, this.regional[ "" ] ); 17986 this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en ); 17987 this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ); 17988} 17989 17990$.extend( Datepicker.prototype, { 17991 17992 /* Class name added to elements to indicate already configured with a date picker. */ 17993 markerClassName: "hasDatepicker", 17994 17995 //Keep track of the maximum number of rows displayed (see #7043) 17996 maxRows: 4, 17997 17998 // TODO rename to "widget" when switching to widget factory 17999 _widgetDatepicker: function() { 18000 return this.dpDiv; 18001 }, 18002 18003 /* Override the default settings for all instances of the date picker. 18004 * @param settings object - the new settings to use as defaults (anonymous object) 18005 * @return the manager object 18006 */ 18007 setDefaults: function( settings ) { 18008 datepicker_extendRemove( this._defaults, settings || {} ); 18009 return this; 18010 }, 18011 18012 /* Attach the date picker to a jQuery selection. 18013 * @param target element - the target input field or division or span 18014 * @param settings object - the new settings to use for this date picker instance (anonymous) 18015 */ 18016 _attachDatepicker: function( target, settings ) { 18017 var nodeName, inline, inst; 18018 nodeName = target.nodeName.toLowerCase(); 18019 inline = ( nodeName === "div" || nodeName === "span" ); 18020 if ( !target.id ) { 18021 this.uuid += 1; 18022 target.id = "dp" + this.uuid; 18023 } 18024 inst = this._newInst( $( target ), inline ); 18025 inst.settings = $.extend( {}, settings || {} ); 18026 if ( nodeName === "input" ) { 18027 this._connectDatepicker( target, inst ); 18028 } else if ( inline ) { 18029 this._inlineDatepicker( target, inst ); 18030 } 18031 }, 18032 18033 /* Create a new instance object. */ 18034 _newInst: function( target, inline ) { 18035 var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars 18036 return { id: id, input: target, // associated target 18037 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 18038 drawMonth: 0, drawYear: 0, // month being drawn 18039 inline: inline, // is datepicker inline or not 18040 dpDiv: ( !inline ? this.dpDiv : // presentation div 18041 datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) }; 18042 }, 18043 18044 /* Attach the date picker to an input field. */ 18045 _connectDatepicker: function( target, inst ) { 18046 var input = $( target ); 18047 inst.append = $( [] ); 18048 inst.trigger = $( [] ); 18049 if ( input.hasClass( this.markerClassName ) ) { 18050 return; 18051 } 18052 this._attachments( input, inst ); 18053 input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ). 18054 on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp ); 18055 this._autoSize( inst ); 18056 $.data( target, "datepicker", inst ); 18057 18058 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 18059 if ( inst.settings.disabled ) { 18060 this._disableDatepicker( target ); 18061 } 18062 }, 18063 18064 /* Make attachments based on settings. */ 18065 _attachments: function( input, inst ) { 18066 var showOn, buttonText, buttonImage, 18067 appendText = this._get( inst, "appendText" ), 18068 isRTL = this._get( inst, "isRTL" ); 18069 18070 if ( inst.append ) { 18071 inst.append.remove(); 18072 } 18073 if ( appendText ) { 18074 inst.append = $( "<span>" ) 18075 .addClass( this._appendClass ) 18076 .text( appendText ); 18077 input[ isRTL ? "before" : "after" ]( inst.append ); 18078 } 18079 18080 input.off( "focus", this._showDatepicker ); 18081 18082 if ( inst.trigger ) { 18083 inst.trigger.remove(); 18084 } 18085 18086 showOn = this._get( inst, "showOn" ); 18087 if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field 18088 input.on( "focus", this._showDatepicker ); 18089 } 18090 if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked 18091 buttonText = this._get( inst, "buttonText" ); 18092 buttonImage = this._get( inst, "buttonImage" ); 18093 18094 if ( this._get( inst, "buttonImageOnly" ) ) { 18095 inst.trigger = $( "<img>" ) 18096 .addClass( this._triggerClass ) 18097 .attr( { 18098 src: buttonImage, 18099 alt: buttonText, 18100 title: buttonText 18101 } ); 18102 } else { 18103 inst.trigger = $( "<button type='button'>" ) 18104 .addClass( this._triggerClass ); 18105 if ( buttonImage ) { 18106 inst.trigger.html( 18107 $( "<img>" ) 18108 .attr( { 18109 src: buttonImage, 18110 alt: buttonText, 18111 title: buttonText 18112 } ) 18113 ); 18114 } else { 18115 inst.trigger.text( buttonText ); 18116 } 18117 } 18118 18119 input[ isRTL ? "before" : "after" ]( inst.trigger ); 18120 inst.trigger.on( "click", function() { 18121 if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) { 18122 $.datepicker._hideDatepicker(); 18123 } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) { 18124 $.datepicker._hideDatepicker(); 18125 $.datepicker._showDatepicker( input[ 0 ] ); 18126 } else { 18127 $.datepicker._showDatepicker( input[ 0 ] ); 18128 } 18129 return false; 18130 } ); 18131 } 18132 }, 18133 18134 /* Apply the maximum length for the date format. */ 18135 _autoSize: function( inst ) { 18136 if ( this._get( inst, "autoSize" ) && !inst.inline ) { 18137 var findMax, max, maxI, i, 18138 date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits 18139 dateFormat = this._get( inst, "dateFormat" ); 18140 18141 if ( dateFormat.match( /[DM]/ ) ) { 18142 findMax = function( names ) { 18143 max = 0; 18144 maxI = 0; 18145 for ( i = 0; i < names.length; i++ ) { 18146 if ( names[ i ].length > max ) { 18147 max = names[ i ].length; 18148 maxI = i; 18149 } 18150 } 18151 return maxI; 18152 }; 18153 date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ? 18154 "monthNames" : "monthNamesShort" ) ) ) ); 18155 date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ? 18156 "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() ); 18157 } 18158 inst.input.attr( "size", this._formatDate( inst, date ).length ); 18159 } 18160 }, 18161 18162 /* Attach an inline date picker to a div. */ 18163 _inlineDatepicker: function( target, inst ) { 18164 var divSpan = $( target ); 18165 if ( divSpan.hasClass( this.markerClassName ) ) { 18166 return; 18167 } 18168 divSpan.addClass( this.markerClassName ).append( inst.dpDiv ); 18169 $.data( target, "datepicker", inst ); 18170 this._setDate( inst, this._getDefaultDate( inst ), true ); 18171 this._updateDatepicker( inst ); 18172 this._updateAlternate( inst ); 18173 18174 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 18175 if ( inst.settings.disabled ) { 18176 this._disableDatepicker( target ); 18177 } 18178 18179 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 18180 // https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 18181 inst.dpDiv.css( "display", "block" ); 18182 }, 18183 18184 /* Pop-up the date picker in a "dialog" box. 18185 * @param input element - ignored 18186 * @param date string or Date - the initial date to display 18187 * @param onSelect function - the function to call when a date is selected 18188 * @param settings object - update the dialog date picker instance's settings (anonymous object) 18189 * @param pos int[2] - coordinates for the dialog's position within the screen or 18190 * event - with x/y coordinates or 18191 * leave empty for default (screen centre) 18192 * @return the manager object 18193 */ 18194 _dialogDatepicker: function( input, date, onSelect, settings, pos ) { 18195 var id, browserWidth, browserHeight, scrollX, scrollY, 18196 inst = this._dialogInst; // internal instance 18197 18198 if ( !inst ) { 18199 this.uuid += 1; 18200 id = "dp" + this.uuid; 18201 this._dialogInput = $( "<input type='text' id='" + id + 18202 "' style='position: absolute; top: -100px; width: 0px;'/>" ); 18203 this._dialogInput.on( "keydown", this._doKeyDown ); 18204 $( "body" ).append( this._dialogInput ); 18205 inst = this._dialogInst = this._newInst( this._dialogInput, false ); 18206 inst.settings = {}; 18207 $.data( this._dialogInput[ 0 ], "datepicker", inst ); 18208 } 18209 datepicker_extendRemove( inst.settings, settings || {} ); 18210 date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date ); 18211 this._dialogInput.val( date ); 18212 18213 this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null ); 18214 if ( !this._pos ) { 18215 browserWidth = document.documentElement.clientWidth; 18216 browserHeight = document.documentElement.clientHeight; 18217 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 18218 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 18219 this._pos = // should use actual width/height below 18220 [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ]; 18221 } 18222 18223 // Move input on screen for focus, but hidden behind dialog 18224 this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" ); 18225 inst.settings.onSelect = onSelect; 18226 this._inDialog = true; 18227 this.dpDiv.addClass( this._dialogClass ); 18228 this._showDatepicker( this._dialogInput[ 0 ] ); 18229 if ( $.blockUI ) { 18230 $.blockUI( this.dpDiv ); 18231 } 18232 $.data( this._dialogInput[ 0 ], "datepicker", inst ); 18233 return this; 18234 }, 18235 18236 /* Detach a datepicker from its control. 18237 * @param target element - the target input field or division or span 18238 */ 18239 _destroyDatepicker: function( target ) { 18240 var nodeName, 18241 $target = $( target ), 18242 inst = $.data( target, "datepicker" ); 18243 18244 if ( !$target.hasClass( this.markerClassName ) ) { 18245 return; 18246 } 18247 18248 nodeName = target.nodeName.toLowerCase(); 18249 $.removeData( target, "datepicker" ); 18250 if ( nodeName === "input" ) { 18251 inst.append.remove(); 18252 inst.trigger.remove(); 18253 $target.removeClass( this.markerClassName ). 18254 off( "focus", this._showDatepicker ). 18255 off( "keydown", this._doKeyDown ). 18256 off( "keypress", this._doKeyPress ). 18257 off( "keyup", this._doKeyUp ); 18258 } else if ( nodeName === "div" || nodeName === "span" ) { 18259 $target.removeClass( this.markerClassName ).empty(); 18260 } 18261 18262 $.datepicker._hideDatepicker(); 18263 if ( datepicker_instActive === inst ) { 18264 datepicker_instActive = null; 18265 this._curInst = null; 18266 } 18267 }, 18268 18269 /* Enable the date picker to a jQuery selection. 18270 * @param target element - the target input field or division or span 18271 */ 18272 _enableDatepicker: function( target ) { 18273 var nodeName, inline, 18274 $target = $( target ), 18275 inst = $.data( target, "datepicker" ); 18276 18277 if ( !$target.hasClass( this.markerClassName ) ) { 18278 return; 18279 } 18280 18281 nodeName = target.nodeName.toLowerCase(); 18282 if ( nodeName === "input" ) { 18283 target.disabled = false; 18284 inst.trigger.filter( "button" ). 18285 each( function() { 18286 this.disabled = false; 18287 } ).end(). 18288 filter( "img" ).css( { opacity: "1.0", cursor: "" } ); 18289 } else if ( nodeName === "div" || nodeName === "span" ) { 18290 inline = $target.children( "." + this._inlineClass ); 18291 inline.children().removeClass( "ui-state-disabled" ); 18292 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ). 18293 prop( "disabled", false ); 18294 } 18295 this._disabledInputs = $.map( this._disabledInputs, 18296 18297 // Delete entry 18298 function( value ) { 18299 return ( value === target ? null : value ); 18300 } ); 18301 }, 18302 18303 /* Disable the date picker to a jQuery selection. 18304 * @param target element - the target input field or division or span 18305 */ 18306 _disableDatepicker: function( target ) { 18307 var nodeName, inline, 18308 $target = $( target ), 18309 inst = $.data( target, "datepicker" ); 18310 18311 if ( !$target.hasClass( this.markerClassName ) ) { 18312 return; 18313 } 18314 18315 nodeName = target.nodeName.toLowerCase(); 18316 if ( nodeName === "input" ) { 18317 target.disabled = true; 18318 inst.trigger.filter( "button" ). 18319 each( function() { 18320 this.disabled = true; 18321 } ).end(). 18322 filter( "img" ).css( { opacity: "0.5", cursor: "default" } ); 18323 } else if ( nodeName === "div" || nodeName === "span" ) { 18324 inline = $target.children( "." + this._inlineClass ); 18325 inline.children().addClass( "ui-state-disabled" ); 18326 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ). 18327 prop( "disabled", true ); 18328 } 18329 this._disabledInputs = $.map( this._disabledInputs, 18330 18331 // Delete entry 18332 function( value ) { 18333 return ( value === target ? null : value ); 18334 } ); 18335 this._disabledInputs[ this._disabledInputs.length ] = target; 18336 }, 18337 18338 /* Is the first field in a jQuery collection disabled as a datepicker? 18339 * @param target element - the target input field or division or span 18340 * @return boolean - true if disabled, false if enabled 18341 */ 18342 _isDisabledDatepicker: function( target ) { 18343 if ( !target ) { 18344 return false; 18345 } 18346 for ( var i = 0; i < this._disabledInputs.length; i++ ) { 18347 if ( this._disabledInputs[ i ] === target ) { 18348 return true; 18349 } 18350 } 18351 return false; 18352 }, 18353 18354 /* Retrieve the instance data for the target control. 18355 * @param target element - the target input field or division or span 18356 * @return object - the associated instance data 18357 * @throws error if a jQuery problem getting data 18358 */ 18359 _getInst: function( target ) { 18360 try { 18361 return $.data( target, "datepicker" ); 18362 } catch ( err ) { 18363 throw "Missing instance data for this datepicker"; 18364 } 18365 }, 18366 18367 /* Update or retrieve the settings for a date picker attached to an input field or division. 18368 * @param target element - the target input field or division or span 18369 * @param name object - the new settings to update or 18370 * string - the name of the setting to change or retrieve, 18371 * when retrieving also "all" for all instance settings or 18372 * "defaults" for all global defaults 18373 * @param value any - the new value for the setting 18374 * (omit if above is an object or to retrieve a value) 18375 */ 18376 _optionDatepicker: function( target, name, value ) { 18377 var settings, date, minDate, maxDate, 18378 inst = this._getInst( target ); 18379 18380 if ( arguments.length === 2 && typeof name === "string" ) { 18381 return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) : 18382 ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) : 18383 this._get( inst, name ) ) : null ) ); 18384 } 18385 18386 settings = name || {}; 18387 if ( typeof name === "string" ) { 18388 settings = {}; 18389 settings[ name ] = value; 18390 } 18391 18392 if ( inst ) { 18393 if ( this._curInst === inst ) { 18394 this._hideDatepicker(); 18395 } 18396 18397 date = this._getDateDatepicker( target, true ); 18398 minDate = this._getMinMaxDate( inst, "min" ); 18399 maxDate = this._getMinMaxDate( inst, "max" ); 18400 datepicker_extendRemove( inst.settings, settings ); 18401 18402 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 18403 if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) { 18404 inst.settings.minDate = this._formatDate( inst, minDate ); 18405 } 18406 if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) { 18407 inst.settings.maxDate = this._formatDate( inst, maxDate ); 18408 } 18409 if ( "disabled" in settings ) { 18410 if ( settings.disabled ) { 18411 this._disableDatepicker( target ); 18412 } else { 18413 this._enableDatepicker( target ); 18414 } 18415 } 18416 this._attachments( $( target ), inst ); 18417 this._autoSize( inst ); 18418 this._setDate( inst, date ); 18419 this._updateAlternate( inst ); 18420 this._updateDatepicker( inst ); 18421 } 18422 }, 18423 18424 // Change method deprecated 18425 _changeDatepicker: function( target, name, value ) { 18426 this._optionDatepicker( target, name, value ); 18427 }, 18428 18429 /* Redraw the date picker attached to an input field or division. 18430 * @param target element - the target input field or division or span 18431 */ 18432 _refreshDatepicker: function( target ) { 18433 var inst = this._getInst( target ); 18434 if ( inst ) { 18435 this._updateDatepicker( inst ); 18436 } 18437 }, 18438 18439 /* Set the dates for a jQuery selection. 18440 * @param target element - the target input field or division or span 18441 * @param date Date - the new date 18442 */ 18443 _setDateDatepicker: function( target, date ) { 18444 var inst = this._getInst( target ); 18445 if ( inst ) { 18446 this._setDate( inst, date ); 18447 this._updateDatepicker( inst ); 18448 this._updateAlternate( inst ); 18449 } 18450 }, 18451 18452 /* Get the date(s) for the first entry in a jQuery selection. 18453 * @param target element - the target input field or division or span 18454 * @param noDefault boolean - true if no default date is to be used 18455 * @return Date - the current date 18456 */ 18457 _getDateDatepicker: function( target, noDefault ) { 18458 var inst = this._getInst( target ); 18459 if ( inst && !inst.inline ) { 18460 this._setDateFromField( inst, noDefault ); 18461 } 18462 return ( inst ? this._getDate( inst ) : null ); 18463 }, 18464 18465 /* Handle keystrokes. */ 18466 _doKeyDown: function( event ) { 18467 var onSelect, dateStr, sel, 18468 inst = $.datepicker._getInst( event.target ), 18469 handled = true, 18470 isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" ); 18471 18472 inst._keyEvent = true; 18473 if ( $.datepicker._datepickerShowing ) { 18474 switch ( event.keyCode ) { 18475 case 9: $.datepicker._hideDatepicker(); 18476 handled = false; 18477 break; // hide on tab out 18478 case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." + 18479 $.datepicker._currentClass + ")", inst.dpDiv ); 18480 if ( sel[ 0 ] ) { 18481 $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] ); 18482 } 18483 18484 onSelect = $.datepicker._get( inst, "onSelect" ); 18485 if ( onSelect ) { 18486 dateStr = $.datepicker._formatDate( inst ); 18487 18488 // Trigger custom callback 18489 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); 18490 } else { 18491 $.datepicker._hideDatepicker(); 18492 } 18493 18494 return false; // don't submit the form 18495 case 27: $.datepicker._hideDatepicker(); 18496 break; // hide on escape 18497 case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 18498 -$.datepicker._get( inst, "stepBigMonths" ) : 18499 -$.datepicker._get( inst, "stepMonths" ) ), "M" ); 18500 break; // previous month/year on page up/+ ctrl 18501 case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 18502 +$.datepicker._get( inst, "stepBigMonths" ) : 18503 +$.datepicker._get( inst, "stepMonths" ) ), "M" ); 18504 break; // next month/year on page down/+ ctrl 18505 case 35: if ( event.ctrlKey || event.metaKey ) { 18506 $.datepicker._clearDate( event.target ); 18507 } 18508 handled = event.ctrlKey || event.metaKey; 18509 break; // clear on ctrl or command +end 18510 case 36: if ( event.ctrlKey || event.metaKey ) { 18511 $.datepicker._gotoToday( event.target ); 18512 } 18513 handled = event.ctrlKey || event.metaKey; 18514 break; // current on ctrl or command +home 18515 case 37: if ( event.ctrlKey || event.metaKey ) { 18516 $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" ); 18517 } 18518 handled = event.ctrlKey || event.metaKey; 18519 18520 // -1 day on ctrl or command +left 18521 if ( event.originalEvent.altKey ) { 18522 $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 18523 -$.datepicker._get( inst, "stepBigMonths" ) : 18524 -$.datepicker._get( inst, "stepMonths" ) ), "M" ); 18525 } 18526 18527 // next month/year on alt +left on Mac 18528 break; 18529 case 38: if ( event.ctrlKey || event.metaKey ) { 18530 $.datepicker._adjustDate( event.target, -7, "D" ); 18531 } 18532 handled = event.ctrlKey || event.metaKey; 18533 break; // -1 week on ctrl or command +up 18534 case 39: if ( event.ctrlKey || event.metaKey ) { 18535 $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" ); 18536 } 18537 handled = event.ctrlKey || event.metaKey; 18538 18539 // +1 day on ctrl or command +right 18540 if ( event.originalEvent.altKey ) { 18541 $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 18542 +$.datepicker._get( inst, "stepBigMonths" ) : 18543 +$.datepicker._get( inst, "stepMonths" ) ), "M" ); 18544 } 18545 18546 // next month/year on alt +right 18547 break; 18548 case 40: if ( event.ctrlKey || event.metaKey ) { 18549 $.datepicker._adjustDate( event.target, +7, "D" ); 18550 } 18551 handled = event.ctrlKey || event.metaKey; 18552 break; // +1 week on ctrl or command +down 18553 default: handled = false; 18554 } 18555 } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home 18556 $.datepicker._showDatepicker( this ); 18557 } else { 18558 handled = false; 18559 } 18560 18561 if ( handled ) { 18562 event.preventDefault(); 18563 event.stopPropagation(); 18564 } 18565 }, 18566 18567 /* Filter entered characters - based on date format. */ 18568 _doKeyPress: function( event ) { 18569 var chars, chr, 18570 inst = $.datepicker._getInst( event.target ); 18571 18572 if ( $.datepicker._get( inst, "constrainInput" ) ) { 18573 chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) ); 18574 chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode ); 18575 return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 ); 18576 } 18577 }, 18578 18579 /* Synchronise manual entry and field/alternate field. */ 18580 _doKeyUp: function( event ) { 18581 var date, 18582 inst = $.datepicker._getInst( event.target ); 18583 18584 if ( inst.input.val() !== inst.lastVal ) { 18585 try { 18586 date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ), 18587 ( inst.input ? inst.input.val() : null ), 18588 $.datepicker._getFormatConfig( inst ) ); 18589 18590 if ( date ) { // only if valid 18591 $.datepicker._setDateFromField( inst ); 18592 $.datepicker._updateAlternate( inst ); 18593 $.datepicker._updateDatepicker( inst ); 18594 } 18595 } catch ( err ) { 18596 } 18597 } 18598 return true; 18599 }, 18600 18601 /* Pop-up the date picker for a given input field. 18602 * If false returned from beforeShow event handler do not show. 18603 * @param input element - the input field attached to the date picker or 18604 * event - if triggered by focus 18605 */ 18606 _showDatepicker: function( input ) { 18607 input = input.target || input; 18608 if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger 18609 input = $( "input", input.parentNode )[ 0 ]; 18610 } 18611 18612 if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here 18613 return; 18614 } 18615 18616 var inst, beforeShow, beforeShowSettings, isFixed, 18617 offset, showAnim, duration; 18618 18619 inst = $.datepicker._getInst( input ); 18620 if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) { 18621 $.datepicker._curInst.dpDiv.stop( true, true ); 18622 if ( inst && $.datepicker._datepickerShowing ) { 18623 $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] ); 18624 } 18625 } 18626 18627 beforeShow = $.datepicker._get( inst, "beforeShow" ); 18628 beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {}; 18629 if ( beforeShowSettings === false ) { 18630 return; 18631 } 18632 datepicker_extendRemove( inst.settings, beforeShowSettings ); 18633 18634 inst.lastVal = null; 18635 $.datepicker._lastInput = input; 18636 $.datepicker._setDateFromField( inst ); 18637 18638 if ( $.datepicker._inDialog ) { // hide cursor 18639 input.value = ""; 18640 } 18641 if ( !$.datepicker._pos ) { // position below input 18642 $.datepicker._pos = $.datepicker._findPos( input ); 18643 $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height 18644 } 18645 18646 isFixed = false; 18647 $( input ).parents().each( function() { 18648 isFixed |= $( this ).css( "position" ) === "fixed"; 18649 return !isFixed; 18650 } ); 18651 18652 offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] }; 18653 $.datepicker._pos = null; 18654 18655 //to avoid flashes on Firefox 18656 inst.dpDiv.empty(); 18657 18658 // determine sizing offscreen 18659 inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } ); 18660 $.datepicker._updateDatepicker( inst ); 18661 18662 // fix width for dynamic number of date pickers 18663 // and adjust position before showing 18664 offset = $.datepicker._checkOffset( inst, offset, isFixed ); 18665 inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ? 18666 "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none", 18667 left: offset.left + "px", top: offset.top + "px" } ); 18668 18669 if ( !inst.inline ) { 18670 showAnim = $.datepicker._get( inst, "showAnim" ); 18671 duration = $.datepicker._get( inst, "duration" ); 18672 inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 ); 18673 $.datepicker._datepickerShowing = true; 18674 18675 if ( $.effects && $.effects.effect[ showAnim ] ) { 18676 inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration ); 18677 } else { 18678 inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null ); 18679 } 18680 18681 if ( $.datepicker._shouldFocusInput( inst ) ) { 18682 inst.input.trigger( "focus" ); 18683 } 18684 18685 $.datepicker._curInst = inst; 18686 } 18687 }, 18688 18689 /* Generate the date picker content. */ 18690 _updateDatepicker: function( inst ) { 18691 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 18692 datepicker_instActive = inst; // for delegate hover events 18693 inst.dpDiv.empty().append( this._generateHTML( inst ) ); 18694 this._attachHandlers( inst ); 18695 18696 var origyearshtml, 18697 numMonths = this._getNumberOfMonths( inst ), 18698 cols = numMonths[ 1 ], 18699 width = 17, 18700 activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ), 18701 onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" ); 18702 18703 if ( activeCell.length > 0 ) { 18704 datepicker_handleMouseover.apply( activeCell.get( 0 ) ); 18705 } 18706 18707 inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" ); 18708 if ( cols > 1 ) { 18709 inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" ); 18710 } 18711 inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) + 18712 "Class" ]( "ui-datepicker-multi" ); 18713 inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) + 18714 "Class" ]( "ui-datepicker-rtl" ); 18715 18716 if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { 18717 inst.input.trigger( "focus" ); 18718 } 18719 18720 // Deffered render of the years select (to avoid flashes on Firefox) 18721 if ( inst.yearshtml ) { 18722 origyearshtml = inst.yearshtml; 18723 setTimeout( function() { 18724 18725 //assure that inst.yearshtml didn't change. 18726 if ( origyearshtml === inst.yearshtml && inst.yearshtml ) { 18727 inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml ); 18728 } 18729 origyearshtml = inst.yearshtml = null; 18730 }, 0 ); 18731 } 18732 18733 if ( onUpdateDatepicker ) { 18734 onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] ); 18735 } 18736 }, 18737 18738 _shouldFocusInput: function( inst ) { 18739 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ); 18740 }, 18741 18742 /* Check positioning to remain on screen. */ 18743 _checkOffset: function( inst, offset, isFixed ) { 18744 var dpWidth = inst.dpDiv.outerWidth(), 18745 dpHeight = inst.dpDiv.outerHeight(), 18746 inputWidth = inst.input ? inst.input.outerWidth() : 0, 18747 inputHeight = inst.input ? inst.input.outerHeight() : 0, 18748 viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ), 18749 viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() ); 18750 18751 offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 ); 18752 offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0; 18753 offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0; 18754 18755 // Now check if datepicker is showing outside window viewport - move to a better place if so. 18756 offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ? 18757 Math.abs( offset.left + dpWidth - viewWidth ) : 0 ); 18758 offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ? 18759 Math.abs( dpHeight + inputHeight ) : 0 ); 18760 18761 return offset; 18762 }, 18763 18764 /* Find an object's position on the screen. */ 18765 _findPos: function( obj ) { 18766 var position, 18767 inst = this._getInst( obj ), 18768 isRTL = this._get( inst, "isRTL" ); 18769 18770 while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) { 18771 obj = obj[ isRTL ? "previousSibling" : "nextSibling" ]; 18772 } 18773 18774 position = $( obj ).offset(); 18775 return [ position.left, position.top ]; 18776 }, 18777 18778 /* Hide the date picker from view. 18779 * @param input element - the input field attached to the date picker 18780 */ 18781 _hideDatepicker: function( input ) { 18782 var showAnim, duration, postProcess, onClose, 18783 inst = this._curInst; 18784 18785 if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) { 18786 return; 18787 } 18788 18789 if ( this._datepickerShowing ) { 18790 showAnim = this._get( inst, "showAnim" ); 18791 duration = this._get( inst, "duration" ); 18792 postProcess = function() { 18793 $.datepicker._tidyDialog( inst ); 18794 }; 18795 18796 if ( $.effects && ( $.effects.effect[ showAnim ] ) ) { 18797 inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess ); 18798 } else { 18799 inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" : 18800 ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess ); 18801 } 18802 18803 if ( !showAnim ) { 18804 postProcess(); 18805 } 18806 this._datepickerShowing = false; 18807 18808 onClose = this._get( inst, "onClose" ); 18809 if ( onClose ) { 18810 onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] ); 18811 } 18812 18813 this._lastInput = null; 18814 if ( this._inDialog ) { 18815 this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } ); 18816 if ( $.blockUI ) { 18817 $.unblockUI(); 18818 $( "body" ).append( this.dpDiv ); 18819 } 18820 } 18821 this._inDialog = false; 18822 } 18823 }, 18824 18825 /* Tidy up after a dialog display. */ 18826 _tidyDialog: function( inst ) { 18827 inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" ); 18828 }, 18829 18830 /* Close date picker if clicked elsewhere. */ 18831 _checkExternalClick: function( event ) { 18832 if ( !$.datepicker._curInst ) { 18833 return; 18834 } 18835 18836 var $target = $( event.target ), 18837 inst = $.datepicker._getInst( $target[ 0 ] ); 18838 18839 if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId && 18840 $target.parents( "#" + $.datepicker._mainDivId ).length === 0 && 18841 !$target.hasClass( $.datepicker.markerClassName ) && 18842 !$target.closest( "." + $.datepicker._triggerClass ).length && 18843 $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) || 18844 ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) { 18845 $.datepicker._hideDatepicker(); 18846 } 18847 }, 18848 18849 /* Adjust one of the date sub-fields. */ 18850 _adjustDate: function( id, offset, period ) { 18851 var target = $( id ), 18852 inst = this._getInst( target[ 0 ] ); 18853 18854 if ( this._isDisabledDatepicker( target[ 0 ] ) ) { 18855 return; 18856 } 18857 this._adjustInstDate( inst, offset, period ); 18858 this._updateDatepicker( inst ); 18859 }, 18860 18861 /* Action for current link. */ 18862 _gotoToday: function( id ) { 18863 var date, 18864 target = $( id ), 18865 inst = this._getInst( target[ 0 ] ); 18866 18867 if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) { 18868 inst.selectedDay = inst.currentDay; 18869 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 18870 inst.drawYear = inst.selectedYear = inst.currentYear; 18871 } else { 18872 date = new Date(); 18873 inst.selectedDay = date.getDate(); 18874 inst.drawMonth = inst.selectedMonth = date.getMonth(); 18875 inst.drawYear = inst.selectedYear = date.getFullYear(); 18876 } 18877 this._notifyChange( inst ); 18878 this._adjustDate( target ); 18879 }, 18880 18881 /* Action for selecting a new month/year. */ 18882 _selectMonthYear: function( id, select, period ) { 18883 var target = $( id ), 18884 inst = this._getInst( target[ 0 ] ); 18885 18886 inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] = 18887 inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] = 18888 parseInt( select.options[ select.selectedIndex ].value, 10 ); 18889 18890 this._notifyChange( inst ); 18891 this._adjustDate( target ); 18892 }, 18893 18894 /* Action for selecting a day. */ 18895 _selectDay: function( id, month, year, td ) { 18896 var inst, 18897 target = $( id ); 18898 18899 if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) { 18900 return; 18901 } 18902 18903 inst = this._getInst( target[ 0 ] ); 18904 inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) ); 18905 inst.selectedMonth = inst.currentMonth = month; 18906 inst.selectedYear = inst.currentYear = year; 18907 this._selectDate( id, this._formatDate( inst, 18908 inst.currentDay, inst.currentMonth, inst.currentYear ) ); 18909 }, 18910 18911 /* Erase the input field and hide the date picker. */ 18912 _clearDate: function( id ) { 18913 var target = $( id ); 18914 this._selectDate( target, "" ); 18915 }, 18916 18917 /* Update the input field with the selected date. */ 18918 _selectDate: function( id, dateStr ) { 18919 var onSelect, 18920 target = $( id ), 18921 inst = this._getInst( target[ 0 ] ); 18922 18923 dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) ); 18924 if ( inst.input ) { 18925 inst.input.val( dateStr ); 18926 } 18927 this._updateAlternate( inst ); 18928 18929 onSelect = this._get( inst, "onSelect" ); 18930 if ( onSelect ) { 18931 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); // trigger custom callback 18932 } else if ( inst.input ) { 18933 inst.input.trigger( "change" ); // fire the change event 18934 } 18935 18936 if ( inst.inline ) { 18937 this._updateDatepicker( inst ); 18938 } else { 18939 this._hideDatepicker(); 18940 this._lastInput = inst.input[ 0 ]; 18941 if ( typeof( inst.input[ 0 ] ) !== "object" ) { 18942 inst.input.trigger( "focus" ); // restore focus 18943 } 18944 this._lastInput = null; 18945 } 18946 }, 18947 18948 /* Update any alternate field to synchronise with the main field. */ 18949 _updateAlternate: function( inst ) { 18950 var altFormat, date, dateStr, 18951 altField = this._get( inst, "altField" ); 18952 18953 if ( altField ) { // update alternate field too 18954 altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" ); 18955 date = this._getDate( inst ); 18956 dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) ); 18957 $( document ).find( altField ).val( dateStr ); 18958 } 18959 }, 18960 18961 /* Set as beforeShowDay function to prevent selection of weekends. 18962 * @param date Date - the date to customise 18963 * @return [boolean, string] - is this date selectable?, what is its CSS class? 18964 */ 18965 noWeekends: function( date ) { 18966 var day = date.getDay(); 18967 return [ ( day > 0 && day < 6 ), "" ]; 18968 }, 18969 18970 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 18971 * @param date Date - the date to get the week for 18972 * @return number - the number of the week within the year that contains this date 18973 */ 18974 iso8601Week: function( date ) { 18975 var time, 18976 checkDate = new Date( date.getTime() ); 18977 18978 // Find Thursday of this week starting on Monday 18979 checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) ); 18980 18981 time = checkDate.getTime(); 18982 checkDate.setMonth( 0 ); // Compare with Jan 1 18983 checkDate.setDate( 1 ); 18984 return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1; 18985 }, 18986 18987 /* Parse a string value into a date object. 18988 * See formatDate below for the possible formats. 18989 * 18990 * @param format string - the expected format of the date 18991 * @param value string - the date in the above format 18992 * @param settings Object - attributes include: 18993 * shortYearCutoff number - the cutoff year for determining the century (optional) 18994 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 18995 * dayNames string[7] - names of the days from Sunday (optional) 18996 * monthNamesShort string[12] - abbreviated names of the months (optional) 18997 * monthNames string[12] - names of the months (optional) 18998 * @return Date - the extracted date value or null if value is blank 18999 */ 19000 parseDate: function( format, value, settings ) { 19001 if ( format == null || value == null ) { 19002 throw "Invalid arguments"; 19003 } 19004 19005 value = ( typeof value === "object" ? value.toString() : value + "" ); 19006 if ( value === "" ) { 19007 return null; 19008 } 19009 19010 var iFormat, dim, extra, 19011 iValue = 0, 19012 shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff, 19013 shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 19014 new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ), 19015 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort, 19016 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames, 19017 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort, 19018 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames, 19019 year = -1, 19020 month = -1, 19021 day = -1, 19022 doy = -1, 19023 literal = false, 19024 date, 19025 19026 // Check whether a format character is doubled 19027 lookAhead = function( match ) { 19028 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 19029 if ( matches ) { 19030 iFormat++; 19031 } 19032 return matches; 19033 }, 19034 19035 // Extract a number from the string value 19036 getNumber = function( match ) { 19037 var isDoubled = lookAhead( match ), 19038 size = ( match === "@" ? 14 : ( match === "!" ? 20 : 19039 ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ), 19040 minSize = ( match === "y" ? size : 1 ), 19041 digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ), 19042 num = value.substring( iValue ).match( digits ); 19043 if ( !num ) { 19044 throw "Missing number at position " + iValue; 19045 } 19046 iValue += num[ 0 ].length; 19047 return parseInt( num[ 0 ], 10 ); 19048 }, 19049 19050 // Extract a name from the string value and convert to an index 19051 getName = function( match, shortNames, longNames ) { 19052 var index = -1, 19053 names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) { 19054 return [ [ k, v ] ]; 19055 } ).sort( function( a, b ) { 19056 return -( a[ 1 ].length - b[ 1 ].length ); 19057 } ); 19058 19059 $.each( names, function( i, pair ) { 19060 var name = pair[ 1 ]; 19061 if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) { 19062 index = pair[ 0 ]; 19063 iValue += name.length; 19064 return false; 19065 } 19066 } ); 19067 if ( index !== -1 ) { 19068 return index + 1; 19069 } else { 19070 throw "Unknown name at position " + iValue; 19071 } 19072 }, 19073 19074 // Confirm that a literal character matches the string value 19075 checkLiteral = function() { 19076 if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) { 19077 throw "Unexpected literal at position " + iValue; 19078 } 19079 iValue++; 19080 }; 19081 19082 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 19083 if ( literal ) { 19084 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 19085 literal = false; 19086 } else { 19087 checkLiteral(); 19088 } 19089 } else { 19090 switch ( format.charAt( iFormat ) ) { 19091 case "d": 19092 day = getNumber( "d" ); 19093 break; 19094 case "D": 19095 getName( "D", dayNamesShort, dayNames ); 19096 break; 19097 case "o": 19098 doy = getNumber( "o" ); 19099 break; 19100 case "m": 19101 month = getNumber( "m" ); 19102 break; 19103 case "M": 19104 month = getName( "M", monthNamesShort, monthNames ); 19105 break; 19106 case "y": 19107 year = getNumber( "y" ); 19108 break; 19109 case "@": 19110 date = new Date( getNumber( "@" ) ); 19111 year = date.getFullYear(); 19112 month = date.getMonth() + 1; 19113 day = date.getDate(); 19114 break; 19115 case "!": 19116 date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 ); 19117 year = date.getFullYear(); 19118 month = date.getMonth() + 1; 19119 day = date.getDate(); 19120 break; 19121 case "'": 19122 if ( lookAhead( "'" ) ) { 19123 checkLiteral(); 19124 } else { 19125 literal = true; 19126 } 19127 break; 19128 default: 19129 checkLiteral(); 19130 } 19131 } 19132 } 19133 19134 if ( iValue < value.length ) { 19135 extra = value.substr( iValue ); 19136 if ( !/^\s+/.test( extra ) ) { 19137 throw "Extra/unparsed characters found in date: " + extra; 19138 } 19139 } 19140 19141 if ( year === -1 ) { 19142 year = new Date().getFullYear(); 19143 } else if ( year < 100 ) { 19144 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 19145 ( year <= shortYearCutoff ? 0 : -100 ); 19146 } 19147 19148 if ( doy > -1 ) { 19149 month = 1; 19150 day = doy; 19151 do { 19152 dim = this._getDaysInMonth( year, month - 1 ); 19153 if ( day <= dim ) { 19154 break; 19155 } 19156 month++; 19157 day -= dim; 19158 } while ( true ); 19159 } 19160 19161 date = this._daylightSavingAdjust( new Date( year, month - 1, day ) ); 19162 if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) { 19163 throw "Invalid date"; // E.g. 31/02/00 19164 } 19165 return date; 19166 }, 19167 19168 /* Standard date formats. */ 19169 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 19170 COOKIE: "D, dd M yy", 19171 ISO_8601: "yy-mm-dd", 19172 RFC_822: "D, d M y", 19173 RFC_850: "DD, dd-M-y", 19174 RFC_1036: "D, d M y", 19175 RFC_1123: "D, d M yy", 19176 RFC_2822: "D, d M yy", 19177 RSS: "D, d M y", // RFC 822 19178 TICKS: "!", 19179 TIMESTAMP: "@", 19180 W3C: "yy-mm-dd", // ISO 8601 19181 19182 _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) + 19183 Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ), 19184 19185 /* Format a date object into a string value. 19186 * The format can be combinations of the following: 19187 * d - day of month (no leading zero) 19188 * dd - day of month (two digit) 19189 * o - day of year (no leading zeros) 19190 * oo - day of year (three digit) 19191 * D - day name short 19192 * DD - day name long 19193 * m - month of year (no leading zero) 19194 * mm - month of year (two digit) 19195 * M - month name short 19196 * MM - month name long 19197 * y - year (two digit) 19198 * yy - year (four digit) 19199 * @ - Unix timestamp (ms since 01/01/1970) 19200 * ! - Windows ticks (100ns since 01/01/0001) 19201 * "..." - literal text 19202 * '' - single quote 19203 * 19204 * @param format string - the desired format of the date 19205 * @param date Date - the date value to format 19206 * @param settings Object - attributes include: 19207 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 19208 * dayNames string[7] - names of the days from Sunday (optional) 19209 * monthNamesShort string[12] - abbreviated names of the months (optional) 19210 * monthNames string[12] - names of the months (optional) 19211 * @return string - the date in the above format 19212 */ 19213 formatDate: function( format, date, settings ) { 19214 if ( !date ) { 19215 return ""; 19216 } 19217 19218 var iFormat, 19219 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort, 19220 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames, 19221 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort, 19222 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames, 19223 19224 // Check whether a format character is doubled 19225 lookAhead = function( match ) { 19226 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 19227 if ( matches ) { 19228 iFormat++; 19229 } 19230 return matches; 19231 }, 19232 19233 // Format a number, with leading zero if necessary 19234 formatNumber = function( match, value, len ) { 19235 var num = "" + value; 19236 if ( lookAhead( match ) ) { 19237 while ( num.length < len ) { 19238 num = "0" + num; 19239 } 19240 } 19241 return num; 19242 }, 19243 19244 // Format a name, short or long as requested 19245 formatName = function( match, value, shortNames, longNames ) { 19246 return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] ); 19247 }, 19248 output = "", 19249 literal = false; 19250 19251 if ( date ) { 19252 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 19253 if ( literal ) { 19254 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 19255 literal = false; 19256 } else { 19257 output += format.charAt( iFormat ); 19258 } 19259 } else { 19260 switch ( format.charAt( iFormat ) ) { 19261 case "d": 19262 output += formatNumber( "d", date.getDate(), 2 ); 19263 break; 19264 case "D": 19265 output += formatName( "D", date.getDay(), dayNamesShort, dayNames ); 19266 break; 19267 case "o": 19268 output += formatNumber( "o", 19269 Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 ); 19270 break; 19271 case "m": 19272 output += formatNumber( "m", date.getMonth() + 1, 2 ); 19273 break; 19274 case "M": 19275 output += formatName( "M", date.getMonth(), monthNamesShort, monthNames ); 19276 break; 19277 case "y": 19278 output += ( lookAhead( "y" ) ? date.getFullYear() : 19279 ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 ); 19280 break; 19281 case "@": 19282 output += date.getTime(); 19283 break; 19284 case "!": 19285 output += date.getTime() * 10000 + this._ticksTo1970; 19286 break; 19287 case "'": 19288 if ( lookAhead( "'" ) ) { 19289 output += "'"; 19290 } else { 19291 literal = true; 19292 } 19293 break; 19294 default: 19295 output += format.charAt( iFormat ); 19296 } 19297 } 19298 } 19299 } 19300 return output; 19301 }, 19302 19303 /* Extract all possible characters from the date format. */ 19304 _possibleChars: function( format ) { 19305 var iFormat, 19306 chars = "", 19307 literal = false, 19308 19309 // Check whether a format character is doubled 19310 lookAhead = function( match ) { 19311 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 19312 if ( matches ) { 19313 iFormat++; 19314 } 19315 return matches; 19316 }; 19317 19318 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 19319 if ( literal ) { 19320 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 19321 literal = false; 19322 } else { 19323 chars += format.charAt( iFormat ); 19324 } 19325 } else { 19326 switch ( format.charAt( iFormat ) ) { 19327 case "d": case "m": case "y": case "@": 19328 chars += "0123456789"; 19329 break; 19330 case "D": case "M": 19331 return null; // Accept anything 19332 case "'": 19333 if ( lookAhead( "'" ) ) { 19334 chars += "'"; 19335 } else { 19336 literal = true; 19337 } 19338 break; 19339 default: 19340 chars += format.charAt( iFormat ); 19341 } 19342 } 19343 } 19344 return chars; 19345 }, 19346 19347 /* Get a setting value, defaulting if necessary. */ 19348 _get: function( inst, name ) { 19349 return inst.settings[ name ] !== undefined ? 19350 inst.settings[ name ] : this._defaults[ name ]; 19351 }, 19352 19353 /* Parse existing date and initialise date picker. */ 19354 _setDateFromField: function( inst, noDefault ) { 19355 if ( inst.input.val() === inst.lastVal ) { 19356 return; 19357 } 19358 19359 var dateFormat = this._get( inst, "dateFormat" ), 19360 dates = inst.lastVal = inst.input ? inst.input.val() : null, 19361 defaultDate = this._getDefaultDate( inst ), 19362 date = defaultDate, 19363 settings = this._getFormatConfig( inst ); 19364 19365 try { 19366 date = this.parseDate( dateFormat, dates, settings ) || defaultDate; 19367 } catch ( event ) { 19368 dates = ( noDefault ? "" : dates ); 19369 } 19370 inst.selectedDay = date.getDate(); 19371 inst.drawMonth = inst.selectedMonth = date.getMonth(); 19372 inst.drawYear = inst.selectedYear = date.getFullYear(); 19373 inst.currentDay = ( dates ? date.getDate() : 0 ); 19374 inst.currentMonth = ( dates ? date.getMonth() : 0 ); 19375 inst.currentYear = ( dates ? date.getFullYear() : 0 ); 19376 this._adjustInstDate( inst ); 19377 }, 19378 19379 /* Retrieve the default date shown on opening. */ 19380 _getDefaultDate: function( inst ) { 19381 return this._restrictMinMax( inst, 19382 this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) ); 19383 }, 19384 19385 /* A date may be specified as an exact value or a relative one. */ 19386 _determineDate: function( inst, date, defaultDate ) { 19387 var offsetNumeric = function( offset ) { 19388 var date = new Date(); 19389 date.setDate( date.getDate() + offset ); 19390 return date; 19391 }, 19392 offsetString = function( offset ) { 19393 try { 19394 return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ), 19395 offset, $.datepicker._getFormatConfig( inst ) ); 19396 } catch ( e ) { 19397 19398 // Ignore 19399 } 19400 19401 var date = ( offset.toLowerCase().match( /^c/ ) ? 19402 $.datepicker._getDate( inst ) : null ) || new Date(), 19403 year = date.getFullYear(), 19404 month = date.getMonth(), 19405 day = date.getDate(), 19406 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 19407 matches = pattern.exec( offset ); 19408 19409 while ( matches ) { 19410 switch ( matches[ 2 ] || "d" ) { 19411 case "d" : case "D" : 19412 day += parseInt( matches[ 1 ], 10 ); break; 19413 case "w" : case "W" : 19414 day += parseInt( matches[ 1 ], 10 ) * 7; break; 19415 case "m" : case "M" : 19416 month += parseInt( matches[ 1 ], 10 ); 19417 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) ); 19418 break; 19419 case "y": case "Y" : 19420 year += parseInt( matches[ 1 ], 10 ); 19421 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) ); 19422 break; 19423 } 19424 matches = pattern.exec( offset ); 19425 } 19426 return new Date( year, month, day ); 19427 }, 19428 newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) : 19429 ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) ); 19430 19431 newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate ); 19432 if ( newDate ) { 19433 newDate.setHours( 0 ); 19434 newDate.setMinutes( 0 ); 19435 newDate.setSeconds( 0 ); 19436 newDate.setMilliseconds( 0 ); 19437 } 19438 return this._daylightSavingAdjust( newDate ); 19439 }, 19440 19441 /* Handle switch to/from daylight saving. 19442 * Hours may be non-zero on daylight saving cut-over: 19443 * > 12 when midnight changeover, but then cannot generate 19444 * midnight datetime, so jump to 1AM, otherwise reset. 19445 * @param date (Date) the date to check 19446 * @return (Date) the corrected date 19447 */ 19448 _daylightSavingAdjust: function( date ) { 19449 if ( !date ) { 19450 return null; 19451 } 19452 date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 ); 19453 return date; 19454 }, 19455 19456 /* Set the date(s) directly. */ 19457 _setDate: function( inst, date, noChange ) { 19458 var clear = !date, 19459 origMonth = inst.selectedMonth, 19460 origYear = inst.selectedYear, 19461 newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) ); 19462 19463 inst.selectedDay = inst.currentDay = newDate.getDate(); 19464 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 19465 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 19466 if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) { 19467 this._notifyChange( inst ); 19468 } 19469 this._adjustInstDate( inst ); 19470 if ( inst.input ) { 19471 inst.input.val( clear ? "" : this._formatDate( inst ) ); 19472 } 19473 }, 19474 19475 /* Retrieve the date(s) directly. */ 19476 _getDate: function( inst ) { 19477 var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null : 19478 this._daylightSavingAdjust( new Date( 19479 inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); 19480 return startDate; 19481 }, 19482 19483 /* Attach the onxxx handlers. These are declared statically so 19484 * they work with static code transformers like Caja. 19485 */ 19486 _attachHandlers: function( inst ) { 19487 var stepMonths = this._get( inst, "stepMonths" ), 19488 id = "#" + inst.id.replace( /\\\\/g, "\\" ); 19489 inst.dpDiv.find( "[data-handler]" ).map( function() { 19490 var handler = { 19491 prev: function() { 19492 $.datepicker._adjustDate( id, -stepMonths, "M" ); 19493 }, 19494 next: function() { 19495 $.datepicker._adjustDate( id, +stepMonths, "M" ); 19496 }, 19497 hide: function() { 19498 $.datepicker._hideDatepicker(); 19499 }, 19500 today: function() { 19501 $.datepicker._gotoToday( id ); 19502 }, 19503 selectDay: function() { 19504 $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this ); 19505 return false; 19506 }, 19507 selectMonth: function() { 19508 $.datepicker._selectMonthYear( id, this, "M" ); 19509 return false; 19510 }, 19511 selectYear: function() { 19512 $.datepicker._selectMonthYear( id, this, "Y" ); 19513 return false; 19514 } 19515 }; 19516 $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] ); 19517 } ); 19518 }, 19519 19520 /* Generate the HTML for the current state of the date picker. */ 19521 _generateHTML: function( inst ) { 19522 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 19523 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 19524 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 19525 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 19526 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 19527 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 19528 tempDate = new Date(), 19529 today = this._daylightSavingAdjust( 19530 new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time 19531 isRTL = this._get( inst, "isRTL" ), 19532 showButtonPanel = this._get( inst, "showButtonPanel" ), 19533 hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ), 19534 navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ), 19535 numMonths = this._getNumberOfMonths( inst ), 19536 showCurrentAtPos = this._get( inst, "showCurrentAtPos" ), 19537 stepMonths = this._get( inst, "stepMonths" ), 19538 isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ), 19539 currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) : 19540 new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ), 19541 minDate = this._getMinMaxDate( inst, "min" ), 19542 maxDate = this._getMinMaxDate( inst, "max" ), 19543 drawMonth = inst.drawMonth - showCurrentAtPos, 19544 drawYear = inst.drawYear; 19545 19546 if ( drawMonth < 0 ) { 19547 drawMonth += 12; 19548 drawYear--; 19549 } 19550 if ( maxDate ) { 19551 maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(), 19552 maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) ); 19553 maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw ); 19554 while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) { 19555 drawMonth--; 19556 if ( drawMonth < 0 ) { 19557 drawMonth = 11; 19558 drawYear--; 19559 } 19560 } 19561 } 19562 inst.drawMonth = drawMonth; 19563 inst.drawYear = drawYear; 19564 19565 prevText = this._get( inst, "prevText" ); 19566 prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText, 19567 this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ), 19568 this._getFormatConfig( inst ) ) ); 19569 19570 if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) { 19571 prev = $( "<a>" ) 19572 .attr( { 19573 "class": "ui-datepicker-prev ui-corner-all", 19574 "data-handler": "prev", 19575 "data-event": "click", 19576 title: prevText 19577 } ) 19578 .append( 19579 $( "<span>" ) 19580 .addClass( "ui-icon ui-icon-circle-triangle-" + 19581 ( isRTL ? "e" : "w" ) ) 19582 .text( prevText ) 19583 )[ 0 ].outerHTML; 19584 } else if ( hideIfNoPrevNext ) { 19585 prev = ""; 19586 } else { 19587 prev = $( "<a>" ) 19588 .attr( { 19589 "class": "ui-datepicker-prev ui-corner-all ui-state-disabled", 19590 title: prevText 19591 } ) 19592 .append( 19593 $( "<span>" ) 19594 .addClass( "ui-icon ui-icon-circle-triangle-" + 19595 ( isRTL ? "e" : "w" ) ) 19596 .text( prevText ) 19597 )[ 0 ].outerHTML; 19598 } 19599 19600 nextText = this._get( inst, "nextText" ); 19601 nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText, 19602 this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ), 19603 this._getFormatConfig( inst ) ) ); 19604 19605 if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) { 19606 next = $( "<a>" ) 19607 .attr( { 19608 "class": "ui-datepicker-next ui-corner-all", 19609 "data-handler": "next", 19610 "data-event": "click", 19611 title: nextText 19612 } ) 19613 .append( 19614 $( "<span>" ) 19615 .addClass( "ui-icon ui-icon-circle-triangle-" + 19616 ( isRTL ? "w" : "e" ) ) 19617 .text( nextText ) 19618 )[ 0 ].outerHTML; 19619 } else if ( hideIfNoPrevNext ) { 19620 next = ""; 19621 } else { 19622 next = $( "<a>" ) 19623 .attr( { 19624 "class": "ui-datepicker-next ui-corner-all ui-state-disabled", 19625 title: nextText 19626 } ) 19627 .append( 19628 $( "<span>" ) 19629 .attr( "class", "ui-icon ui-icon-circle-triangle-" + 19630 ( isRTL ? "w" : "e" ) ) 19631 .text( nextText ) 19632 )[ 0 ].outerHTML; 19633 } 19634 19635 currentText = this._get( inst, "currentText" ); 19636 gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today ); 19637 currentText = ( !navigationAsDateFormat ? currentText : 19638 this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) ); 19639 19640 controls = ""; 19641 if ( !inst.inline ) { 19642 controls = $( "<button>" ) 19643 .attr( { 19644 type: "button", 19645 "class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all", 19646 "data-handler": "hide", 19647 "data-event": "click" 19648 } ) 19649 .text( this._get( inst, "closeText" ) )[ 0 ].outerHTML; 19650 } 19651 19652 buttonPanel = ""; 19653 if ( showButtonPanel ) { 19654 buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" ) 19655 .append( isRTL ? controls : "" ) 19656 .append( this._isInRange( inst, gotoDate ) ? 19657 $( "<button>" ) 19658 .attr( { 19659 type: "button", 19660 "class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all", 19661 "data-handler": "today", 19662 "data-event": "click" 19663 } ) 19664 .text( currentText ) : 19665 "" ) 19666 .append( isRTL ? "" : controls )[ 0 ].outerHTML; 19667 } 19668 19669 firstDay = parseInt( this._get( inst, "firstDay" ), 10 ); 19670 firstDay = ( isNaN( firstDay ) ? 0 : firstDay ); 19671 19672 showWeek = this._get( inst, "showWeek" ); 19673 dayNames = this._get( inst, "dayNames" ); 19674 dayNamesMin = this._get( inst, "dayNamesMin" ); 19675 monthNames = this._get( inst, "monthNames" ); 19676 monthNamesShort = this._get( inst, "monthNamesShort" ); 19677 beforeShowDay = this._get( inst, "beforeShowDay" ); 19678 showOtherMonths = this._get( inst, "showOtherMonths" ); 19679 selectOtherMonths = this._get( inst, "selectOtherMonths" ); 19680 defaultDate = this._getDefaultDate( inst ); 19681 html = ""; 19682 19683 for ( row = 0; row < numMonths[ 0 ]; row++ ) { 19684 group = ""; 19685 this.maxRows = 4; 19686 for ( col = 0; col < numMonths[ 1 ]; col++ ) { 19687 selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) ); 19688 cornerClass = " ui-corner-all"; 19689 calender = ""; 19690 if ( isMultiMonth ) { 19691 calender += "<div class='ui-datepicker-group"; 19692 if ( numMonths[ 1 ] > 1 ) { 19693 switch ( col ) { 19694 case 0: calender += " ui-datepicker-group-first"; 19695 cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break; 19696 case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last"; 19697 cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break; 19698 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 19699 } 19700 } 19701 calender += "'>"; 19702 } 19703 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 19704 ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) + 19705 ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) + 19706 this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate, 19707 row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers 19708 "</div><table class='ui-datepicker-calendar'><thead>" + 19709 "<tr>"; 19710 thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" ); 19711 for ( dow = 0; dow < 7; dow++ ) { // days of the week 19712 day = ( dow + firstDay ) % 7; 19713 thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" + 19714 "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>"; 19715 } 19716 calender += thead + "</tr></thead><tbody>"; 19717 daysInMonth = this._getDaysInMonth( drawYear, drawMonth ); 19718 if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) { 19719 inst.selectedDay = Math.min( inst.selectedDay, daysInMonth ); 19720 } 19721 leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7; 19722 curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate 19723 numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043) 19724 this.maxRows = numRows; 19725 printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) ); 19726 for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows 19727 calender += "<tr>"; 19728 tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 19729 this._get( inst, "calculateWeek" )( printDate ) + "</td>" ); 19730 for ( dow = 0; dow < 7; dow++ ) { // create date picker days 19731 daySettings = ( beforeShowDay ? 19732 beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] ); 19733 otherMonth = ( printDate.getMonth() !== drawMonth ); 19734 unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] || 19735 ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate ); 19736 tbody += "<td class='" + 19737 ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends 19738 ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months 19739 ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key 19740 ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ? 19741 19742 // or defaultDate is current printedDate and defaultDate is selectedDate 19743 " " + this._dayOverClass : "" ) + // highlight selected day 19744 ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) + // highlight unselectable days 19745 ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates 19746 ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day 19747 ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different) 19748 ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "'" ) + "'" : "" ) + // cell title 19749 ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions 19750 ( otherMonth && !showOtherMonths ? " " : // display for other months 19751 ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 19752 ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) + 19753 ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day 19754 ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months 19755 "' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader 19756 "' data-date='" + printDate.getDate() + // store date as data 19757 "'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date 19758 printDate.setDate( printDate.getDate() + 1 ); 19759 printDate = this._daylightSavingAdjust( printDate ); 19760 } 19761 calender += tbody + "</tr>"; 19762 } 19763 drawMonth++; 19764 if ( drawMonth > 11 ) { 19765 drawMonth = 0; 19766 drawYear++; 19767 } 19768 calender += "</tbody></table>" + ( isMultiMonth ? "</div>" + 19769 ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" ); 19770 group += calender; 19771 } 19772 html += group; 19773 } 19774 html += buttonPanel; 19775 inst._keyEvent = false; 19776 return html; 19777 }, 19778 19779 /* Generate the month and year header. */ 19780 _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate, 19781 secondary, monthNames, monthNamesShort ) { 19782 19783 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 19784 changeMonth = this._get( inst, "changeMonth" ), 19785 changeYear = this._get( inst, "changeYear" ), 19786 showMonthAfterYear = this._get( inst, "showMonthAfterYear" ), 19787 selectMonthLabel = this._get( inst, "selectMonthLabel" ), 19788 selectYearLabel = this._get( inst, "selectYearLabel" ), 19789 html = "<div class='ui-datepicker-title'>", 19790 monthHtml = ""; 19791 19792 // Month selection 19793 if ( secondary || !changeMonth ) { 19794 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>"; 19795 } else { 19796 inMinYear = ( minDate && minDate.getFullYear() === drawYear ); 19797 inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear ); 19798 monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>"; 19799 for ( month = 0; month < 12; month++ ) { 19800 if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) { 19801 monthHtml += "<option value='" + month + "'" + 19802 ( month === drawMonth ? " selected='selected'" : "" ) + 19803 ">" + monthNamesShort[ month ] + "</option>"; 19804 } 19805 } 19806 monthHtml += "</select>"; 19807 } 19808 19809 if ( !showMonthAfterYear ) { 19810 html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? " " : "" ); 19811 } 19812 19813 // Year selection 19814 if ( !inst.yearshtml ) { 19815 inst.yearshtml = ""; 19816 if ( secondary || !changeYear ) { 19817 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 19818 } else { 19819 19820 // determine range of years to display 19821 years = this._get( inst, "yearRange" ).split( ":" ); 19822 thisYear = new Date().getFullYear(); 19823 determineYear = function( value ) { 19824 var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) : 19825 ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) : 19826 parseInt( value, 10 ) ) ); 19827 return ( isNaN( year ) ? thisYear : year ); 19828 }; 19829 year = determineYear( years[ 0 ] ); 19830 endYear = Math.max( year, determineYear( years[ 1 ] || "" ) ); 19831 year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year ); 19832 endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear ); 19833 inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>"; 19834 for ( ; year <= endYear; year++ ) { 19835 inst.yearshtml += "<option value='" + year + "'" + 19836 ( year === drawYear ? " selected='selected'" : "" ) + 19837 ">" + year + "</option>"; 19838 } 19839 inst.yearshtml += "</select>"; 19840 19841 html += inst.yearshtml; 19842 inst.yearshtml = null; 19843 } 19844 } 19845 19846 html += this._get( inst, "yearSuffix" ); 19847 if ( showMonthAfterYear ) { 19848 html += ( secondary || !( changeMonth && changeYear ) ? " " : "" ) + monthHtml; 19849 } 19850 html += "</div>"; // Close datepicker_header 19851 return html; 19852 }, 19853 19854 /* Adjust one of the date sub-fields. */ 19855 _adjustInstDate: function( inst, offset, period ) { 19856 var year = inst.selectedYear + ( period === "Y" ? offset : 0 ), 19857 month = inst.selectedMonth + ( period === "M" ? offset : 0 ), 19858 day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ), 19859 date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) ); 19860 19861 inst.selectedDay = date.getDate(); 19862 inst.drawMonth = inst.selectedMonth = date.getMonth(); 19863 inst.drawYear = inst.selectedYear = date.getFullYear(); 19864 if ( period === "M" || period === "Y" ) { 19865 this._notifyChange( inst ); 19866 } 19867 }, 19868 19869 /* Ensure a date is within any min/max bounds. */ 19870 _restrictMinMax: function( inst, date ) { 19871 var minDate = this._getMinMaxDate( inst, "min" ), 19872 maxDate = this._getMinMaxDate( inst, "max" ), 19873 newDate = ( minDate && date < minDate ? minDate : date ); 19874 return ( maxDate && newDate > maxDate ? maxDate : newDate ); 19875 }, 19876 19877 /* Notify change of month/year. */ 19878 _notifyChange: function( inst ) { 19879 var onChange = this._get( inst, "onChangeMonthYear" ); 19880 if ( onChange ) { 19881 onChange.apply( ( inst.input ? inst.input[ 0 ] : null ), 19882 [ inst.selectedYear, inst.selectedMonth + 1, inst ] ); 19883 } 19884 }, 19885 19886 /* Determine the number of months to show. */ 19887 _getNumberOfMonths: function( inst ) { 19888 var numMonths = this._get( inst, "numberOfMonths" ); 19889 return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) ); 19890 }, 19891 19892 /* Determine the current maximum date - ensure no time components are set. */ 19893 _getMinMaxDate: function( inst, minMax ) { 19894 return this._determineDate( inst, this._get( inst, minMax + "Date" ), null ); 19895 }, 19896 19897 /* Find the number of days in a given month. */ 19898 _getDaysInMonth: function( year, month ) { 19899 return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate(); 19900 }, 19901 19902 /* Find the day of the week of the first of a month. */ 19903 _getFirstDayOfMonth: function( year, month ) { 19904 return new Date( year, month, 1 ).getDay(); 19905 }, 19906 19907 /* Determines if we should allow a "next/prev" month display change. */ 19908 _canAdjustMonth: function( inst, offset, curYear, curMonth ) { 19909 var numMonths = this._getNumberOfMonths( inst ), 19910 date = this._daylightSavingAdjust( new Date( curYear, 19911 curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) ); 19912 19913 if ( offset < 0 ) { 19914 date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) ); 19915 } 19916 return this._isInRange( inst, date ); 19917 }, 19918 19919 /* Is the given date in the accepted range? */ 19920 _isInRange: function( inst, date ) { 19921 var yearSplit, currentYear, 19922 minDate = this._getMinMaxDate( inst, "min" ), 19923 maxDate = this._getMinMaxDate( inst, "max" ), 19924 minYear = null, 19925 maxYear = null, 19926 years = this._get( inst, "yearRange" ); 19927 if ( years ) { 19928 yearSplit = years.split( ":" ); 19929 currentYear = new Date().getFullYear(); 19930 minYear = parseInt( yearSplit[ 0 ], 10 ); 19931 maxYear = parseInt( yearSplit[ 1 ], 10 ); 19932 if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) { 19933 minYear += currentYear; 19934 } 19935 if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) { 19936 maxYear += currentYear; 19937 } 19938 } 19939 19940 return ( ( !minDate || date.getTime() >= minDate.getTime() ) && 19941 ( !maxDate || date.getTime() <= maxDate.getTime() ) && 19942 ( !minYear || date.getFullYear() >= minYear ) && 19943 ( !maxYear || date.getFullYear() <= maxYear ) ); 19944 }, 19945 19946 /* Provide the configuration settings for formatting/parsing. */ 19947 _getFormatConfig: function( inst ) { 19948 var shortYearCutoff = this._get( inst, "shortYearCutoff" ); 19949 shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff : 19950 new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) ); 19951 return { shortYearCutoff: shortYearCutoff, 19952 dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ), 19953 monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) }; 19954 }, 19955 19956 /* Format the given date for display. */ 19957 _formatDate: function( inst, day, month, year ) { 19958 if ( !day ) { 19959 inst.currentDay = inst.selectedDay; 19960 inst.currentMonth = inst.selectedMonth; 19961 inst.currentYear = inst.selectedYear; 19962 } 19963 var date = ( day ? ( typeof day === "object" ? day : 19964 this._daylightSavingAdjust( new Date( year, month, day ) ) ) : 19965 this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); 19966 return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) ); 19967 } 19968} ); 19969 19970/* 19971 * Bind hover events for datepicker elements. 19972 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 19973 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 19974 */ 19975function datepicker_bindHover( dpDiv ) { 19976 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 19977 return dpDiv.on( "mouseout", selector, function() { 19978 $( this ).removeClass( "ui-state-hover" ); 19979 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) { 19980 $( this ).removeClass( "ui-datepicker-prev-hover" ); 19981 } 19982 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) { 19983 $( this ).removeClass( "ui-datepicker-next-hover" ); 19984 } 19985 } ) 19986 .on( "mouseover", selector, datepicker_handleMouseover ); 19987} 19988 19989function datepicker_handleMouseover() { 19990 if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) { 19991 $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" ); 19992 $( this ).addClass( "ui-state-hover" ); 19993 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) { 19994 $( this ).addClass( "ui-datepicker-prev-hover" ); 19995 } 19996 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) { 19997 $( this ).addClass( "ui-datepicker-next-hover" ); 19998 } 19999 } 20000} 20001 20002/* jQuery extend now ignores nulls! */ 20003function datepicker_extendRemove( target, props ) { 20004 $.extend( target, props ); 20005 for ( var name in props ) { 20006 if ( props[ name ] == null ) { 20007 target[ name ] = props[ name ]; 20008 } 20009 } 20010 return target; 20011} 20012 20013/* Invoke the datepicker functionality. 20014 @param options string - a command, optionally followed by additional parameters or 20015 Object - settings for attaching new datepicker functionality 20016 @return jQuery object */ 20017$.fn.datepicker = function( options ) { 20018 20019 /* Verify an empty collection wasn't passed - Fixes #6976 */ 20020 if ( !this.length ) { 20021 return this; 20022 } 20023 20024 /* Initialise the date picker. */ 20025 if ( !$.datepicker.initialized ) { 20026 $( document ).on( "mousedown", $.datepicker._checkExternalClick ); 20027 $.datepicker.initialized = true; 20028 } 20029 20030 /* Append datepicker main container to body if not exist. */ 20031 if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) { 20032 $( "body" ).append( $.datepicker.dpDiv ); 20033 } 20034 20035 var otherArgs = Array.prototype.slice.call( arguments, 1 ); 20036 if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) { 20037 return $.datepicker[ "_" + options + "Datepicker" ]. 20038 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) ); 20039 } 20040 if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) { 20041 return $.datepicker[ "_" + options + "Datepicker" ]. 20042 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) ); 20043 } 20044 return this.each( function() { 20045 if ( typeof options === "string" ) { 20046 $.datepicker[ "_" + options + "Datepicker" ] 20047 .apply( $.datepicker, [ this ].concat( otherArgs ) ); 20048 } else { 20049 $.datepicker._attachDatepicker( this, options ); 20050 } 20051 } ); 20052}; 20053 20054$.datepicker = new Datepicker(); // singleton instance 20055$.datepicker.initialized = false; 20056$.datepicker.uuid = new Date().getTime(); 20057$.datepicker.version = "1.14.1"; 20058 20059var widgetsDatepicker = $.datepicker; 20060 20061 20062/*! 20063 * jQuery UI Mouse 1.14.1 20064 * https://jqueryui.com 20065 * 20066 * Copyright OpenJS Foundation and other contributors 20067 * Released under the MIT license. 20068 * https://jquery.org/license 20069 */ 20070 20071//>>label: Mouse 20072//>>group: Widgets 20073//>>description: Abstracts mouse-based interactions to assist in creating certain widgets. 20074//>>docs: https://api.jqueryui.com/mouse/ 20075 20076 20077var mouseHandled = false; 20078$( document ).on( "mouseup", function() { 20079 mouseHandled = false; 20080} ); 20081 20082var widgetsMouse = $.widget( "ui.mouse", { 20083 version: "1.14.1", 20084 options: { 20085 cancel: "input, textarea, button, select, option", 20086 distance: 1, 20087 delay: 0 20088 }, 20089 _mouseInit: function() { 20090 var that = this; 20091 20092 this.element 20093 .on( "mousedown." + this.widgetName, function( event ) { 20094 return that._mouseDown( event ); 20095 } ) 20096 .on( "click." + this.widgetName, function( event ) { 20097 if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) { 20098 $.removeData( event.target, that.widgetName + ".preventClickEvent" ); 20099 event.stopImmediatePropagation(); 20100 return false; 20101 } 20102 } ); 20103 20104 this.started = false; 20105 }, 20106 20107 // TODO: make sure destroying one instance of mouse doesn't mess with 20108 // other instances of mouse 20109 _mouseDestroy: function() { 20110 this.element.off( "." + this.widgetName ); 20111 if ( this._mouseMoveDelegate ) { 20112 this.document 20113 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 20114 .off( "mouseup." + this.widgetName, this._mouseUpDelegate ); 20115 } 20116 }, 20117 20118 _mouseDown: function( event ) { 20119 20120 // don't let more than one widget handle mouseStart 20121 if ( mouseHandled ) { 20122 return; 20123 } 20124 20125 this._mouseMoved = false; 20126 20127 // We may have missed mouseup (out of window) 20128 if ( this._mouseStarted ) { 20129 this._mouseUp( event ); 20130 } 20131 20132 this._mouseDownEvent = event; 20133 20134 var that = this, 20135 btnIsLeft = event.which === 1, 20136 elIsCancel = typeof this.options.cancel === "string" ? 20137 $( event.target ).closest( this.options.cancel ).length : 20138 false; 20139 if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) { 20140 return true; 20141 } 20142 20143 this.mouseDelayMet = !this.options.delay; 20144 if ( !this.mouseDelayMet ) { 20145 this._mouseDelayTimer = setTimeout( function() { 20146 that.mouseDelayMet = true; 20147 }, this.options.delay ); 20148 } 20149 20150 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) { 20151 this._mouseStarted = ( this._mouseStart( event ) !== false ); 20152 if ( !this._mouseStarted ) { 20153 event.preventDefault(); 20154 return true; 20155 } 20156 } 20157 20158 // Click event may never have fired (Gecko & Opera) 20159 if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) { 20160 $.removeData( event.target, this.widgetName + ".preventClickEvent" ); 20161 } 20162 20163 // These delegates are required to keep context 20164 this._mouseMoveDelegate = function( event ) { 20165 return that._mouseMove( event ); 20166 }; 20167 this._mouseUpDelegate = function( event ) { 20168 return that._mouseUp( event ); 20169 }; 20170 20171 this.document 20172 .on( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 20173 .on( "mouseup." + this.widgetName, this._mouseUpDelegate ); 20174 20175 event.preventDefault(); 20176 20177 mouseHandled = true; 20178 return true; 20179 }, 20180 20181 _mouseMove: function( event ) { 20182 20183 // Only check for mouseups outside the document if you've moved inside the document 20184 // at least once. 20185 if ( this._mouseMoved && !event.which ) { 20186 20187 // Support: Safari <=8 - 9 20188 // Safari sets which to 0 if you press any of the following keys 20189 // during a drag (#14461) 20190 if ( event.originalEvent.altKey || event.originalEvent.ctrlKey || 20191 event.originalEvent.metaKey || event.originalEvent.shiftKey ) { 20192 this.ignoreMissingWhich = true; 20193 } else if ( !this.ignoreMissingWhich ) { 20194 return this._mouseUp( event ); 20195 } 20196 } 20197 20198 if ( event.which || event.button ) { 20199 this._mouseMoved = true; 20200 } 20201 20202 if ( this._mouseStarted ) { 20203 this._mouseDrag( event ); 20204 return event.preventDefault(); 20205 } 20206 20207 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) { 20208 this._mouseStarted = 20209 ( this._mouseStart( this._mouseDownEvent, event ) !== false ); 20210 if ( this._mouseStarted ) { 20211 this._mouseDrag( event ); 20212 } else { 20213 this._mouseUp( event ); 20214 } 20215 } 20216 20217 return !this._mouseStarted; 20218 }, 20219 20220 _mouseUp: function( event ) { 20221 this.document 20222 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 20223 .off( "mouseup." + this.widgetName, this._mouseUpDelegate ); 20224 20225 if ( this._mouseStarted ) { 20226 this._mouseStarted = false; 20227 20228 if ( event.target === this._mouseDownEvent.target ) { 20229 $.data( event.target, this.widgetName + ".preventClickEvent", true ); 20230 } 20231 20232 this._mouseStop( event ); 20233 } 20234 20235 if ( this._mouseDelayTimer ) { 20236 clearTimeout( this._mouseDelayTimer ); 20237 delete this._mouseDelayTimer; 20238 } 20239 20240 this.ignoreMissingWhich = false; 20241 mouseHandled = false; 20242 event.preventDefault(); 20243 }, 20244 20245 _mouseDistanceMet: function( event ) { 20246 return ( Math.max( 20247 Math.abs( this._mouseDownEvent.pageX - event.pageX ), 20248 Math.abs( this._mouseDownEvent.pageY - event.pageY ) 20249 ) >= this.options.distance 20250 ); 20251 }, 20252 20253 _mouseDelayMet: function( /* event */ ) { 20254 return this.mouseDelayMet; 20255 }, 20256 20257 // These are placeholder methods, to be overriden by extending plugin 20258 _mouseStart: function( /* event */ ) {}, 20259 _mouseDrag: function( /* event */ ) {}, 20260 _mouseStop: function( /* event */ ) {}, 20261 _mouseCapture: function( /* event */ ) { 20262 return true; 20263 } 20264} ); 20265 20266 20267 20268// $.ui.plugin is deprecated. Use $.widget() extensions instead. 20269var plugin = $.ui.plugin = { 20270 add: function( module, option, set ) { 20271 var i, 20272 proto = $.ui[ module ].prototype; 20273 for ( i in set ) { 20274 proto.plugins[ i ] = proto.plugins[ i ] || []; 20275 proto.plugins[ i ].push( [ option, set[ i ] ] ); 20276 } 20277 }, 20278 call: function( instance, name, args, allowDisconnected ) { 20279 var i, 20280 set = instance.plugins[ name ]; 20281 20282 if ( !set ) { 20283 return; 20284 } 20285 20286 if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || 20287 instance.element[ 0 ].parentNode.nodeType === 11 ) ) { 20288 return; 20289 } 20290 20291 for ( i = 0; i < set.length; i++ ) { 20292 if ( instance.options[ set[ i ][ 0 ] ] ) { 20293 set[ i ][ 1 ].apply( instance.element, args ); 20294 } 20295 } 20296 } 20297}; 20298 20299 20300/*! 20301 * jQuery UI Draggable 1.14.1 20302 * https://jqueryui.com 20303 * 20304 * Copyright OpenJS Foundation and other contributors 20305 * Released under the MIT license. 20306 * https://jquery.org/license 20307 */ 20308 20309//>>label: Draggable 20310//>>group: Interactions 20311//>>description: Enables dragging functionality for any element. 20312//>>docs: https://api.jqueryui.com/draggable/ 20313//>>demos: https://jqueryui.com/draggable/ 20314//>>css.structure: ../../themes/base/draggable.css 20315 20316 20317$.widget( "ui.draggable", $.ui.mouse, { 20318 version: "1.14.1", 20319 widgetEventPrefix: "drag", 20320 options: { 20321 addClasses: true, 20322 appendTo: "parent", 20323 axis: false, 20324 connectToSortable: false, 20325 containment: false, 20326 cursor: "auto", 20327 cursorAt: false, 20328 grid: false, 20329 handle: false, 20330 helper: "original", 20331 iframeFix: false, 20332 opacity: false, 20333 refreshPositions: false, 20334 revert: false, 20335 revertDuration: 500, 20336 scope: "default", 20337 scroll: true, 20338 scrollSensitivity: 20, 20339 scrollSpeed: 20, 20340 snap: false, 20341 snapMode: "both", 20342 snapTolerance: 20, 20343 stack: false, 20344 zIndex: false, 20345 20346 // Callbacks 20347 drag: null, 20348 start: null, 20349 stop: null 20350 }, 20351 _create: function() { 20352 20353 if ( this.options.helper === "original" ) { 20354 this._setPositionRelative(); 20355 } 20356 if ( this.options.addClasses ) { 20357 this._addClass( "ui-draggable" ); 20358 } 20359 this._setHandleClassName(); 20360 20361 this._mouseInit(); 20362 }, 20363 20364 _setOption: function( key, value ) { 20365 this._super( key, value ); 20366 if ( key === "handle" ) { 20367 this._removeHandleClassName(); 20368 this._setHandleClassName(); 20369 } 20370 }, 20371 20372 _destroy: function() { 20373 if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) { 20374 this.destroyOnClear = true; 20375 return; 20376 } 20377 this._removeHandleClassName(); 20378 this._mouseDestroy(); 20379 }, 20380 20381 _mouseCapture: function( event ) { 20382 var o = this.options; 20383 20384 // Among others, prevent a drag on a resizable-handle 20385 if ( this.helper || o.disabled || 20386 $( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) { 20387 return false; 20388 } 20389 20390 //Quit if we're not on a valid handle 20391 this.handle = this._getHandle( event ); 20392 if ( !this.handle ) { 20393 return false; 20394 } 20395 20396 this._blurActiveElement( event ); 20397 20398 this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix ); 20399 20400 return true; 20401 20402 }, 20403 20404 _blockFrames: function( selector ) { 20405 this.iframeBlocks = this.document.find( selector ).map( function() { 20406 var iframe = $( this ); 20407 20408 return $( "<div>" ) 20409 .css( "position", "absolute" ) 20410 .appendTo( iframe.parent() ) 20411 .outerWidth( iframe.outerWidth() ) 20412 .outerHeight( iframe.outerHeight() ) 20413 .offset( iframe.offset() )[ 0 ]; 20414 } ); 20415 }, 20416 20417 _unblockFrames: function() { 20418 if ( this.iframeBlocks ) { 20419 this.iframeBlocks.remove(); 20420 delete this.iframeBlocks; 20421 } 20422 }, 20423 20424 _blurActiveElement: function( event ) { 20425 var activeElement = this.document[ 0 ].activeElement, 20426 target = $( event.target ); 20427 20428 // Don't blur if the event occurred on an element that is within 20429 // the currently focused element 20430 // See #10527, #12472 20431 if ( target.closest( activeElement ).length ) { 20432 return; 20433 } 20434 20435 // Blur any element that currently has focus, see #4261 20436 $( activeElement ).trigger( "blur" ); 20437 }, 20438 20439 _mouseStart: function( event ) { 20440 20441 var o = this.options; 20442 20443 //Create and append the visible helper 20444 this.helper = this._createHelper( event ); 20445 20446 this._addClass( this.helper, "ui-draggable-dragging" ); 20447 20448 //Cache the helper size 20449 this._cacheHelperProportions(); 20450 20451 //If ddmanager is used for droppables, set the global draggable 20452 if ( $.ui.ddmanager ) { 20453 $.ui.ddmanager.current = this; 20454 } 20455 20456 /* 20457 * - Position generation - 20458 * This block generates everything position related - it's the core of draggables. 20459 */ 20460 20461 //Cache the margins of the original element 20462 this._cacheMargins(); 20463 20464 //Store the helper's css position 20465 this.cssPosition = this.helper.css( "position" ); 20466 this.scrollParent = this.helper.scrollParent( true ); 20467 this.offsetParent = this.helper.offsetParent(); 20468 this.hasFixedAncestor = this.helper.parents().filter( function() { 20469 return $( this ).css( "position" ) === "fixed"; 20470 } ).length > 0; 20471 20472 //The element's absolute position on the page minus margins 20473 this.positionAbs = this.element.offset(); 20474 this._refreshOffsets( event ); 20475 20476 //Generate the original position 20477 this.originalPosition = this.position = this._generatePosition( event, false ); 20478 this.originalPageX = event.pageX; 20479 this.originalPageY = event.pageY; 20480 20481 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 20482 if ( o.cursorAt ) { 20483 this._adjustOffsetFromHelper( o.cursorAt ); 20484 } 20485 20486 //Set a containment if given in the options 20487 this._setContainment(); 20488 20489 //Trigger event + callbacks 20490 if ( this._trigger( "start", event ) === false ) { 20491 this._clear(); 20492 return false; 20493 } 20494 20495 //Recache the helper size 20496 this._cacheHelperProportions(); 20497 20498 //Prepare the droppable offsets 20499 if ( $.ui.ddmanager && !o.dropBehaviour ) { 20500 $.ui.ddmanager.prepareOffsets( this, event ); 20501 } 20502 20503 // Execute the drag once - this causes the helper not to be visible before getting its 20504 // correct position 20505 this._mouseDrag( event, true ); 20506 20507 // If the ddmanager is used for droppables, inform the manager that dragging has started 20508 // (see #5003) 20509 if ( $.ui.ddmanager ) { 20510 $.ui.ddmanager.dragStart( this, event ); 20511 } 20512 20513 return true; 20514 }, 20515 20516 _refreshOffsets: function( event ) { 20517 this.offset = { 20518 top: this.positionAbs.top - this.margins.top, 20519 left: this.positionAbs.left - this.margins.left, 20520 scroll: false, 20521 parent: this._getParentOffset(), 20522 relative: this._getRelativeOffset() 20523 }; 20524 20525 this.offset.click = { 20526 left: event.pageX - this.offset.left, 20527 top: event.pageY - this.offset.top 20528 }; 20529 }, 20530 20531 _mouseDrag: function( event, noPropagation ) { 20532 20533 // reset any necessary cached properties (see #5009) 20534 if ( this.hasFixedAncestor ) { 20535 this.offset.parent = this._getParentOffset(); 20536 } 20537 20538 //Compute the helpers position 20539 this.position = this._generatePosition( event, true ); 20540 this.positionAbs = this._convertPositionTo( "absolute" ); 20541 20542 //Call plugins and callbacks and use the resulting position if something is returned 20543 if ( !noPropagation ) { 20544 var ui = this._uiHash(); 20545 if ( this._trigger( "drag", event, ui ) === false ) { 20546 this._mouseUp( new $.Event( "mouseup", event ) ); 20547 return false; 20548 } 20549 this.position = ui.position; 20550 } 20551 20552 this.helper[ 0 ].style.left = this.position.left + "px"; 20553 this.helper[ 0 ].style.top = this.position.top + "px"; 20554 20555 if ( $.ui.ddmanager ) { 20556 $.ui.ddmanager.drag( this, event ); 20557 } 20558 20559 return false; 20560 }, 20561 20562 _mouseStop: function( event ) { 20563 20564 //If we are using droppables, inform the manager about the drop 20565 var that = this, 20566 dropped = false; 20567 if ( $.ui.ddmanager && !this.options.dropBehaviour ) { 20568 dropped = $.ui.ddmanager.drop( this, event ); 20569 } 20570 20571 //if a drop comes from outside (a sortable) 20572 if ( this.dropped ) { 20573 dropped = this.dropped; 20574 this.dropped = false; 20575 } 20576 20577 if ( ( this.options.revert === "invalid" && !dropped ) || 20578 ( this.options.revert === "valid" && dropped ) || 20579 this.options.revert === true || ( typeof this.options.revert === "function" && 20580 this.options.revert.call( this.element, dropped ) ) 20581 ) { 20582 $( this.helper ).animate( 20583 this.originalPosition, 20584 parseInt( this.options.revertDuration, 10 ), 20585 function() { 20586 if ( that._trigger( "stop", event ) !== false ) { 20587 that._clear(); 20588 } 20589 } 20590 ); 20591 } else { 20592 if ( this._trigger( "stop", event ) !== false ) { 20593 this._clear(); 20594 } 20595 } 20596 20597 return false; 20598 }, 20599 20600 _mouseUp: function( event ) { 20601 this._unblockFrames(); 20602 20603 // If the ddmanager is used for droppables, inform the manager that dragging has stopped 20604 // (see #5003) 20605 if ( $.ui.ddmanager ) { 20606 $.ui.ddmanager.dragStop( this, event ); 20607 } 20608 20609 // Only need to focus if the event occurred on the draggable itself, see #10527 20610 if ( this.handleElement.is( event.target ) ) { 20611 20612 // The interaction is over; whether or not the click resulted in a drag, 20613 // focus the element 20614 this.element.trigger( "focus" ); 20615 } 20616 20617 return $.ui.mouse.prototype._mouseUp.call( this, event ); 20618 }, 20619 20620 cancel: function() { 20621 20622 if ( this.helper.is( ".ui-draggable-dragging" ) ) { 20623 this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) ); 20624 } else { 20625 this._clear(); 20626 } 20627 20628 return this; 20629 20630 }, 20631 20632 _getHandle: function( event ) { 20633 return this.options.handle ? 20634 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : 20635 true; 20636 }, 20637 20638 _setHandleClassName: function() { 20639 this.handleElement = this.options.handle ? 20640 this.element.find( this.options.handle ) : this.element; 20641 this._addClass( this.handleElement, "ui-draggable-handle" ); 20642 }, 20643 20644 _removeHandleClassName: function() { 20645 this._removeClass( this.handleElement, "ui-draggable-handle" ); 20646 }, 20647 20648 _createHelper: function( event ) { 20649 20650 var o = this.options, 20651 helperIsFunction = typeof o.helper === "function", 20652 helper = helperIsFunction ? 20653 $( o.helper.apply( this.element[ 0 ], [ event ] ) ) : 20654 ( o.helper === "clone" ? 20655 this.element.clone().removeAttr( "id" ) : 20656 this.element ); 20657 20658 if ( !helper.parents( "body" ).length ) { 20659 helper.appendTo( ( o.appendTo === "parent" ? 20660 this.element[ 0 ].parentNode : 20661 o.appendTo ) ); 20662 } 20663 20664 // https://bugs.jqueryui.com/ticket/9446 20665 // a helper function can return the original element 20666 // which wouldn't have been set to relative in _create 20667 if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) { 20668 this._setPositionRelative(); 20669 } 20670 20671 if ( helper[ 0 ] !== this.element[ 0 ] && 20672 !( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) { 20673 helper.css( "position", "absolute" ); 20674 } 20675 20676 return helper; 20677 20678 }, 20679 20680 _setPositionRelative: function() { 20681 if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) { 20682 this.element[ 0 ].style.position = "relative"; 20683 } 20684 }, 20685 20686 _adjustOffsetFromHelper: function( obj ) { 20687 if ( typeof obj === "string" ) { 20688 obj = obj.split( " " ); 20689 } 20690 if ( Array.isArray( obj ) ) { 20691 obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 }; 20692 } 20693 if ( "left" in obj ) { 20694 this.offset.click.left = obj.left + this.margins.left; 20695 } 20696 if ( "right" in obj ) { 20697 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 20698 } 20699 if ( "top" in obj ) { 20700 this.offset.click.top = obj.top + this.margins.top; 20701 } 20702 if ( "bottom" in obj ) { 20703 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 20704 } 20705 }, 20706 20707 _isRootNode: function( element ) { 20708 return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ]; 20709 }, 20710 20711 _getParentOffset: function() { 20712 20713 //Get the offsetParent and cache its position 20714 var po = this.offsetParent.offset(), 20715 document = this.document[ 0 ]; 20716 20717 // This is a special case where we need to modify a offset calculated on start, since the 20718 // following happened: 20719 // 1. The position of the helper is absolute, so it's position is calculated based on the 20720 // next positioned parent 20721 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't 20722 // the document, which means that the scroll is included in the initial calculation of the 20723 // offset of the parent, and never recalculated upon drag 20724 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document && 20725 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { 20726 po.left += this.scrollParent.scrollLeft(); 20727 po.top += this.scrollParent.scrollTop(); 20728 } 20729 20730 if ( this._isRootNode( this.offsetParent[ 0 ] ) ) { 20731 po = { top: 0, left: 0 }; 20732 } 20733 20734 return { 20735 top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ), 20736 left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 ) 20737 }; 20738 20739 }, 20740 20741 _getRelativeOffset: function() { 20742 if ( this.cssPosition !== "relative" ) { 20743 return { top: 0, left: 0 }; 20744 } 20745 20746 var p = this.element.position(), 20747 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 20748 20749 return { 20750 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) + 20751 ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ), 20752 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) + 20753 ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 ) 20754 }; 20755 20756 }, 20757 20758 _cacheMargins: function() { 20759 this.margins = { 20760 left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ), 20761 top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ), 20762 right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ), 20763 bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 ) 20764 }; 20765 }, 20766 20767 _cacheHelperProportions: function() { 20768 this.helperProportions = { 20769 width: this.helper.outerWidth(), 20770 height: this.helper.outerHeight() 20771 }; 20772 }, 20773 20774 _setContainment: function() { 20775 20776 var isUserScrollable, c, ce, 20777 o = this.options, 20778 document = this.document[ 0 ]; 20779 20780 this.relativeContainer = null; 20781 20782 if ( !o.containment ) { 20783 this.containment = null; 20784 return; 20785 } 20786 20787 if ( o.containment === "window" ) { 20788 this.containment = [ 20789 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 20790 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, 20791 $( window ).scrollLeft() + $( window ).width() - 20792 this.helperProportions.width - this.margins.left, 20793 $( window ).scrollTop() + 20794 ( $( window ).height() || document.body.parentNode.scrollHeight ) - 20795 this.helperProportions.height - this.margins.top 20796 ]; 20797 return; 20798 } 20799 20800 if ( o.containment === "document" ) { 20801 this.containment = [ 20802 0, 20803 0, 20804 $( document ).width() - this.helperProportions.width - this.margins.left, 20805 ( $( document ).height() || document.body.parentNode.scrollHeight ) - 20806 this.helperProportions.height - this.margins.top 20807 ]; 20808 return; 20809 } 20810 20811 if ( o.containment.constructor === Array ) { 20812 this.containment = o.containment; 20813 return; 20814 } 20815 20816 if ( o.containment === "parent" ) { 20817 o.containment = this.helper[ 0 ].parentNode; 20818 } 20819 20820 c = $( o.containment ); 20821 ce = c[ 0 ]; 20822 20823 if ( !ce ) { 20824 return; 20825 } 20826 20827 isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) ); 20828 20829 this.containment = [ 20830 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + 20831 ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), 20832 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + 20833 ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ), 20834 ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - 20835 ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - 20836 ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - 20837 this.helperProportions.width - 20838 this.margins.left - 20839 this.margins.right, 20840 ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - 20841 ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - 20842 ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - 20843 this.helperProportions.height - 20844 this.margins.top - 20845 this.margins.bottom 20846 ]; 20847 this.relativeContainer = c; 20848 }, 20849 20850 _convertPositionTo: function( d, pos ) { 20851 20852 if ( !pos ) { 20853 pos = this.position; 20854 } 20855 20856 var mod = d === "absolute" ? 1 : -1, 20857 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 20858 20859 return { 20860 top: ( 20861 20862 // The absolute mouse position 20863 pos.top + 20864 20865 // Only for relative positioned nodes: Relative offset from element to offset parent 20866 this.offset.relative.top * mod + 20867 20868 // The offsetParent's offset without borders (offset + border) 20869 this.offset.parent.top * mod - 20870 ( ( this.cssPosition === "fixed" ? 20871 -this.offset.scroll.top : 20872 ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod ) 20873 ), 20874 left: ( 20875 20876 // The absolute mouse position 20877 pos.left + 20878 20879 // Only for relative positioned nodes: Relative offset from element to offset parent 20880 this.offset.relative.left * mod + 20881 20882 // The offsetParent's offset without borders (offset + border) 20883 this.offset.parent.left * mod - 20884 ( ( this.cssPosition === "fixed" ? 20885 -this.offset.scroll.left : 20886 ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod ) 20887 ) 20888 }; 20889 20890 }, 20891 20892 _generatePosition: function( event, constrainPosition ) { 20893 20894 var containment, co, top, left, 20895 o = this.options, 20896 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ), 20897 pageX = event.pageX, 20898 pageY = event.pageY; 20899 20900 // Cache the scroll 20901 if ( !scrollIsRootNode || !this.offset.scroll ) { 20902 this.offset.scroll = { 20903 top: this.scrollParent.scrollTop(), 20904 left: this.scrollParent.scrollLeft() 20905 }; 20906 } 20907 20908 /* 20909 * - Position constraining - 20910 * Constrain the position to a mix of grid, containment. 20911 */ 20912 20913 // If we are not dragging yet, we won't check for options 20914 if ( constrainPosition ) { 20915 if ( this.containment ) { 20916 if ( this.relativeContainer ) { 20917 co = this.relativeContainer.offset(); 20918 containment = [ 20919 this.containment[ 0 ] + co.left, 20920 this.containment[ 1 ] + co.top, 20921 this.containment[ 2 ] + co.left, 20922 this.containment[ 3 ] + co.top 20923 ]; 20924 } else { 20925 containment = this.containment; 20926 } 20927 20928 if ( event.pageX - this.offset.click.left < containment[ 0 ] ) { 20929 pageX = containment[ 0 ] + this.offset.click.left; 20930 } 20931 if ( event.pageY - this.offset.click.top < containment[ 1 ] ) { 20932 pageY = containment[ 1 ] + this.offset.click.top; 20933 } 20934 if ( event.pageX - this.offset.click.left > containment[ 2 ] ) { 20935 pageX = containment[ 2 ] + this.offset.click.left; 20936 } 20937 if ( event.pageY - this.offset.click.top > containment[ 3 ] ) { 20938 pageY = containment[ 3 ] + this.offset.click.top; 20939 } 20940 } 20941 20942 if ( o.grid ) { 20943 20944 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid 20945 // argument errors in IE (see ticket #6950) 20946 top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY - 20947 this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY; 20948 pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] || 20949 top - this.offset.click.top > containment[ 3 ] ) ? 20950 top : 20951 ( ( top - this.offset.click.top >= containment[ 1 ] ) ? 20952 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top; 20953 20954 left = o.grid[ 0 ] ? this.originalPageX + 20955 Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] : 20956 this.originalPageX; 20957 pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] || 20958 left - this.offset.click.left > containment[ 2 ] ) ? 20959 left : 20960 ( ( left - this.offset.click.left >= containment[ 0 ] ) ? 20961 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left; 20962 } 20963 20964 if ( o.axis === "y" ) { 20965 pageX = this.originalPageX; 20966 } 20967 20968 if ( o.axis === "x" ) { 20969 pageY = this.originalPageY; 20970 } 20971 } 20972 20973 return { 20974 top: ( 20975 20976 // The absolute mouse position 20977 pageY - 20978 20979 // Click offset (relative to the element) 20980 this.offset.click.top - 20981 20982 // Only for relative positioned nodes: Relative offset from element to offset parent 20983 this.offset.relative.top - 20984 20985 // The offsetParent's offset without borders (offset + border) 20986 this.offset.parent.top + 20987 ( this.cssPosition === "fixed" ? 20988 -this.offset.scroll.top : 20989 ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) 20990 ), 20991 left: ( 20992 20993 // The absolute mouse position 20994 pageX - 20995 20996 // Click offset (relative to the element) 20997 this.offset.click.left - 20998 20999 // Only for relative positioned nodes: Relative offset from element to offset parent 21000 this.offset.relative.left - 21001 21002 // The offsetParent's offset without borders (offset + border) 21003 this.offset.parent.left + 21004 ( this.cssPosition === "fixed" ? 21005 -this.offset.scroll.left : 21006 ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) 21007 ) 21008 }; 21009 21010 }, 21011 21012 _clear: function() { 21013 this._removeClass( this.helper, "ui-draggable-dragging" ); 21014 if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) { 21015 this.helper.remove(); 21016 } 21017 this.helper = null; 21018 this.cancelHelperRemoval = false; 21019 if ( this.destroyOnClear ) { 21020 this.destroy(); 21021 } 21022 }, 21023 21024 // From now on bulk stuff - mainly helpers 21025 21026 _trigger: function( type, event, ui ) { 21027 ui = ui || this._uiHash(); 21028 $.ui.plugin.call( this, type, [ event, ui, this ], true ); 21029 21030 // Absolute position and offset (see #6884 ) have to be recalculated after plugins 21031 if ( /^(drag|start|stop)/.test( type ) ) { 21032 this.positionAbs = this._convertPositionTo( "absolute" ); 21033 ui.offset = this.positionAbs; 21034 } 21035 return $.Widget.prototype._trigger.call( this, type, event, ui ); 21036 }, 21037 21038 plugins: {}, 21039 21040 _uiHash: function() { 21041 return { 21042 helper: this.helper, 21043 position: this.position, 21044 originalPosition: this.originalPosition, 21045 offset: this.positionAbs 21046 }; 21047 } 21048 21049} ); 21050 21051$.ui.plugin.add( "draggable", "connectToSortable", { 21052 start: function( event, ui, draggable ) { 21053 var uiSortable = $.extend( {}, ui, { 21054 item: draggable.element 21055 } ); 21056 21057 draggable.sortables = []; 21058 $( draggable.options.connectToSortable ).each( function() { 21059 var sortable = $( this ).sortable( "instance" ); 21060 21061 if ( sortable && !sortable.options.disabled ) { 21062 draggable.sortables.push( sortable ); 21063 21064 // RefreshPositions is called at drag start to refresh the containerCache 21065 // which is used in drag. This ensures it's initialized and synchronized 21066 // with any changes that might have happened on the page since initialization. 21067 sortable.refreshPositions(); 21068 sortable._trigger( "activate", event, uiSortable ); 21069 } 21070 } ); 21071 }, 21072 stop: function( event, ui, draggable ) { 21073 var uiSortable = $.extend( {}, ui, { 21074 item: draggable.element 21075 } ); 21076 21077 draggable.cancelHelperRemoval = false; 21078 21079 $.each( draggable.sortables, function() { 21080 var sortable = this; 21081 21082 if ( sortable.isOver ) { 21083 sortable.isOver = 0; 21084 21085 // Allow this sortable to handle removing the helper 21086 draggable.cancelHelperRemoval = true; 21087 sortable.cancelHelperRemoval = false; 21088 21089 // Use _storedCSS To restore properties in the sortable, 21090 // as this also handles revert (#9675) since the draggable 21091 // may have modified them in unexpected ways (#8809) 21092 sortable._storedCSS = { 21093 position: sortable.placeholder.css( "position" ), 21094 top: sortable.placeholder.css( "top" ), 21095 left: sortable.placeholder.css( "left" ) 21096 }; 21097 21098 sortable._mouseStop( event ); 21099 21100 // Once drag has ended, the sortable should return to using 21101 // its original helper, not the shared helper from draggable 21102 sortable.options.helper = sortable.options._helper; 21103 } else { 21104 21105 // Prevent this Sortable from removing the helper. 21106 // However, don't set the draggable to remove the helper 21107 // either as another connected Sortable may yet handle the removal. 21108 sortable.cancelHelperRemoval = true; 21109 21110 sortable._trigger( "deactivate", event, uiSortable ); 21111 } 21112 } ); 21113 }, 21114 drag: function( event, ui, draggable ) { 21115 $.each( draggable.sortables, function() { 21116 var innermostIntersecting = false, 21117 sortable = this; 21118 21119 // Copy over variables that sortable's _intersectsWith uses 21120 sortable.positionAbs = draggable.positionAbs; 21121 sortable.helperProportions = draggable.helperProportions; 21122 sortable.offset.click = draggable.offset.click; 21123 21124 if ( sortable._intersectsWith( sortable.containerCache ) ) { 21125 innermostIntersecting = true; 21126 21127 $.each( draggable.sortables, function() { 21128 21129 // Copy over variables that sortable's _intersectsWith uses 21130 this.positionAbs = draggable.positionAbs; 21131 this.helperProportions = draggable.helperProportions; 21132 this.offset.click = draggable.offset.click; 21133 21134 if ( this !== sortable && 21135 this._intersectsWith( this.containerCache ) && 21136 $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) { 21137 innermostIntersecting = false; 21138 } 21139 21140 return innermostIntersecting; 21141 } ); 21142 } 21143 21144 if ( innermostIntersecting ) { 21145 21146 // If it intersects, we use a little isOver variable and set it once, 21147 // so that the move-in stuff gets fired only once. 21148 if ( !sortable.isOver ) { 21149 sortable.isOver = 1; 21150 21151 // Store draggable's parent in case we need to reappend to it later. 21152 draggable._parent = ui.helper.parent(); 21153 21154 sortable.currentItem = ui.helper 21155 .appendTo( sortable.element ) 21156 .data( "ui-sortable-item", true ); 21157 21158 // Store helper option to later restore it 21159 sortable.options._helper = sortable.options.helper; 21160 21161 sortable.options.helper = function() { 21162 return ui.helper[ 0 ]; 21163 }; 21164 21165 // Fire the start events of the sortable with our passed browser event, 21166 // and our own helper (so it doesn't create a new one) 21167 event.target = sortable.currentItem[ 0 ]; 21168 sortable._mouseCapture( event, true ); 21169 sortable._mouseStart( event, true, true ); 21170 21171 // Because the browser event is way off the new appended portlet, 21172 // modify necessary variables to reflect the changes 21173 sortable.offset.click.top = draggable.offset.click.top; 21174 sortable.offset.click.left = draggable.offset.click.left; 21175 sortable.offset.parent.left -= draggable.offset.parent.left - 21176 sortable.offset.parent.left; 21177 sortable.offset.parent.top -= draggable.offset.parent.top - 21178 sortable.offset.parent.top; 21179 21180 draggable._trigger( "toSortable", event ); 21181 21182 // Inform draggable that the helper is in a valid drop zone, 21183 // used solely in the revert option to handle "valid/invalid". 21184 draggable.dropped = sortable.element; 21185 21186 // Need to refreshPositions of all sortables in the case that 21187 // adding to one sortable changes the location of the other sortables (#9675) 21188 $.each( draggable.sortables, function() { 21189 this.refreshPositions(); 21190 } ); 21191 21192 // Hack so receive/update callbacks work (mostly) 21193 draggable.currentItem = draggable.element; 21194 sortable.fromOutside = draggable; 21195 } 21196 21197 if ( sortable.currentItem ) { 21198 sortable._mouseDrag( event ); 21199 21200 // Copy the sortable's position because the draggable's can potentially reflect 21201 // a relative position, while sortable is always absolute, which the dragged 21202 // element has now become. (#8809) 21203 ui.position = sortable.position; 21204 } 21205 } else { 21206 21207 // If it doesn't intersect with the sortable, and it intersected before, 21208 // we fake the drag stop of the sortable, but make sure it doesn't remove 21209 // the helper by using cancelHelperRemoval. 21210 if ( sortable.isOver ) { 21211 21212 sortable.isOver = 0; 21213 sortable.cancelHelperRemoval = true; 21214 21215 // Calling sortable's mouseStop would trigger a revert, 21216 // so revert must be temporarily false until after mouseStop is called. 21217 sortable.options._revert = sortable.options.revert; 21218 sortable.options.revert = false; 21219 21220 sortable._trigger( "out", event, sortable._uiHash( sortable ) ); 21221 sortable._mouseStop( event, true ); 21222 21223 // Restore sortable behaviors that were modfied 21224 // when the draggable entered the sortable area (#9481) 21225 sortable.options.revert = sortable.options._revert; 21226 sortable.options.helper = sortable.options._helper; 21227 21228 if ( sortable.placeholder ) { 21229 sortable.placeholder.remove(); 21230 } 21231 21232 // Restore and recalculate the draggable's offset considering the sortable 21233 // may have modified them in unexpected ways. (#8809, #10669) 21234 ui.helper.appendTo( draggable._parent ); 21235 draggable._refreshOffsets( event ); 21236 ui.position = draggable._generatePosition( event, true ); 21237 21238 draggable._trigger( "fromSortable", event ); 21239 21240 // Inform draggable that the helper is no longer in a valid drop zone 21241 draggable.dropped = false; 21242 21243 // Need to refreshPositions of all sortables just in case removing 21244 // from one sortable changes the location of other sortables (#9675) 21245 $.each( draggable.sortables, function() { 21246 this.refreshPositions(); 21247 } ); 21248 } 21249 } 21250 } ); 21251 } 21252} ); 21253 21254$.ui.plugin.add( "draggable", "cursor", { 21255 start: function( event, ui, instance ) { 21256 var t = $( "body" ), 21257 o = instance.options; 21258 21259 if ( t.css( "cursor" ) ) { 21260 o._cursor = t.css( "cursor" ); 21261 } 21262 t.css( "cursor", o.cursor ); 21263 }, 21264 stop: function( event, ui, instance ) { 21265 var o = instance.options; 21266 if ( o._cursor ) { 21267 $( "body" ).css( "cursor", o._cursor ); 21268 } 21269 } 21270} ); 21271 21272$.ui.plugin.add( "draggable", "opacity", { 21273 start: function( event, ui, instance ) { 21274 var t = $( ui.helper ), 21275 o = instance.options; 21276 if ( t.css( "opacity" ) ) { 21277 o._opacity = t.css( "opacity" ); 21278 } 21279 t.css( "opacity", o.opacity ); 21280 }, 21281 stop: function( event, ui, instance ) { 21282 var o = instance.options; 21283 if ( o._opacity ) { 21284 $( ui.helper ).css( "opacity", o._opacity ); 21285 } 21286 } 21287} ); 21288 21289$.ui.plugin.add( "draggable", "scroll", { 21290 start: function( event, ui, i ) { 21291 if ( !i.scrollParentNotHidden ) { 21292 i.scrollParentNotHidden = i.helper.scrollParent( false ); 21293 } 21294 21295 if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && 21296 i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) { 21297 i.overflowOffset = i.scrollParentNotHidden.offset(); 21298 } 21299 }, 21300 drag: function( event, ui, i ) { 21301 21302 var o = i.options, 21303 scrolled = false, 21304 scrollParent = i.scrollParentNotHidden[ 0 ], 21305 document = i.document[ 0 ]; 21306 21307 if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) { 21308 if ( !o.axis || o.axis !== "x" ) { 21309 if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < 21310 o.scrollSensitivity ) { 21311 scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed; 21312 } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) { 21313 scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed; 21314 } 21315 } 21316 21317 if ( !o.axis || o.axis !== "y" ) { 21318 if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < 21319 o.scrollSensitivity ) { 21320 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed; 21321 } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) { 21322 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed; 21323 } 21324 } 21325 21326 } else { 21327 21328 if ( !o.axis || o.axis !== "x" ) { 21329 if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) { 21330 scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed ); 21331 } else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) < 21332 o.scrollSensitivity ) { 21333 scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed ); 21334 } 21335 } 21336 21337 if ( !o.axis || o.axis !== "y" ) { 21338 if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) { 21339 scrolled = $( document ).scrollLeft( 21340 $( document ).scrollLeft() - o.scrollSpeed 21341 ); 21342 } else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) < 21343 o.scrollSensitivity ) { 21344 scrolled = $( document ).scrollLeft( 21345 $( document ).scrollLeft() + o.scrollSpeed 21346 ); 21347 } 21348 } 21349 21350 } 21351 21352 if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) { 21353 $.ui.ddmanager.prepareOffsets( i, event ); 21354 } 21355 21356 } 21357} ); 21358 21359$.ui.plugin.add( "draggable", "snap", { 21360 start: function( event, ui, i ) { 21361 21362 var o = i.options; 21363 21364 i.snapElements = []; 21365 21366 $( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap ) 21367 .each( function() { 21368 var $t = $( this ), 21369 $o = $t.offset(); 21370 if ( this !== i.element[ 0 ] ) { 21371 i.snapElements.push( { 21372 item: this, 21373 width: $t.outerWidth(), height: $t.outerHeight(), 21374 top: $o.top, left: $o.left 21375 } ); 21376 } 21377 } ); 21378 21379 }, 21380 drag: function( event, ui, inst ) { 21381 21382 var ts, bs, ls, rs, l, r, t, b, i, first, 21383 o = inst.options, 21384 d = o.snapTolerance, 21385 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 21386 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 21387 21388 for ( i = inst.snapElements.length - 1; i >= 0; i-- ) { 21389 21390 l = inst.snapElements[ i ].left - inst.margins.left; 21391 r = l + inst.snapElements[ i ].width; 21392 t = inst.snapElements[ i ].top - inst.margins.top; 21393 b = t + inst.snapElements[ i ].height; 21394 21395 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || 21396 !$.contains( inst.snapElements[ i ].item.ownerDocument, 21397 inst.snapElements[ i ].item ) ) { 21398 if ( inst.snapElements[ i ].snapping ) { 21399 if ( inst.options.snap.release ) { 21400 inst.options.snap.release.call( 21401 inst.element, 21402 event, 21403 $.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } ) 21404 ); 21405 } 21406 } 21407 inst.snapElements[ i ].snapping = false; 21408 continue; 21409 } 21410 21411 if ( o.snapMode !== "inner" ) { 21412 ts = Math.abs( t - y2 ) <= d; 21413 bs = Math.abs( b - y1 ) <= d; 21414 ls = Math.abs( l - x2 ) <= d; 21415 rs = Math.abs( r - x1 ) <= d; 21416 if ( ts ) { 21417 ui.position.top = inst._convertPositionTo( "relative", { 21418 top: t - inst.helperProportions.height, 21419 left: 0 21420 } ).top; 21421 } 21422 if ( bs ) { 21423 ui.position.top = inst._convertPositionTo( "relative", { 21424 top: b, 21425 left: 0 21426 } ).top; 21427 } 21428 if ( ls ) { 21429 ui.position.left = inst._convertPositionTo( "relative", { 21430 top: 0, 21431 left: l - inst.helperProportions.width 21432 } ).left; 21433 } 21434 if ( rs ) { 21435 ui.position.left = inst._convertPositionTo( "relative", { 21436 top: 0, 21437 left: r 21438 } ).left; 21439 } 21440 } 21441 21442 first = ( ts || bs || ls || rs ); 21443 21444 if ( o.snapMode !== "outer" ) { 21445 ts = Math.abs( t - y1 ) <= d; 21446 bs = Math.abs( b - y2 ) <= d; 21447 ls = Math.abs( l - x1 ) <= d; 21448 rs = Math.abs( r - x2 ) <= d; 21449 if ( ts ) { 21450 ui.position.top = inst._convertPositionTo( "relative", { 21451 top: t, 21452 left: 0 21453 } ).top; 21454 } 21455 if ( bs ) { 21456 ui.position.top = inst._convertPositionTo( "relative", { 21457 top: b - inst.helperProportions.height, 21458 left: 0 21459 } ).top; 21460 } 21461 if ( ls ) { 21462 ui.position.left = inst._convertPositionTo( "relative", { 21463 top: 0, 21464 left: l 21465 } ).left; 21466 } 21467 if ( rs ) { 21468 ui.position.left = inst._convertPositionTo( "relative", { 21469 top: 0, 21470 left: r - inst.helperProportions.width 21471 } ).left; 21472 } 21473 } 21474 21475 if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) { 21476 if ( inst.options.snap.snap ) { 21477 inst.options.snap.snap.call( 21478 inst.element, 21479 event, 21480 $.extend( inst._uiHash(), { 21481 snapItem: inst.snapElements[ i ].item 21482 } ) ); 21483 } 21484 } 21485 inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first ); 21486 21487 } 21488 21489 } 21490} ); 21491 21492$.ui.plugin.add( "draggable", "stack", { 21493 start: function( event, ui, instance ) { 21494 var min, 21495 o = instance.options, 21496 group = $.makeArray( $( o.stack ) ).sort( function( a, b ) { 21497 return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) - 21498 ( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 ); 21499 } ); 21500 21501 if ( !group.length ) { 21502 return; 21503 } 21504 21505 min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0; 21506 $( group ).each( function( i ) { 21507 $( this ).css( "zIndex", min + i ); 21508 } ); 21509 this.css( "zIndex", ( min + group.length ) ); 21510 } 21511} ); 21512 21513$.ui.plugin.add( "draggable", "zIndex", { 21514 start: function( event, ui, instance ) { 21515 var t = $( ui.helper ), 21516 o = instance.options; 21517 21518 if ( t.css( "zIndex" ) ) { 21519 o._zIndex = t.css( "zIndex" ); 21520 } 21521 t.css( "zIndex", o.zIndex ); 21522 }, 21523 stop: function( event, ui, instance ) { 21524 var o = instance.options; 21525 21526 if ( o._zIndex ) { 21527 $( ui.helper ).css( "zIndex", o._zIndex ); 21528 } 21529 } 21530} ); 21531 21532var widgetsDraggable = $.ui.draggable; 21533 21534 21535/*! 21536 * jQuery UI Resizable 1.14.1 21537 * https://jqueryui.com 21538 * 21539 * Copyright OpenJS Foundation and other contributors 21540 * Released under the MIT license. 21541 * https://jquery.org/license 21542 */ 21543 21544//>>label: Resizable 21545//>>group: Interactions 21546//>>description: Enables resize functionality for any element. 21547//>>docs: https://api.jqueryui.com/resizable/ 21548//>>demos: https://jqueryui.com/resizable/ 21549//>>css.structure: ../../themes/base/core.css 21550//>>css.structure: ../../themes/base/resizable.css 21551//>>css.theme: ../../themes/base/theme.css 21552 21553 21554$.widget( "ui.resizable", $.ui.mouse, { 21555 version: "1.14.1", 21556 widgetEventPrefix: "resize", 21557 options: { 21558 alsoResize: false, 21559 animate: false, 21560 animateDuration: "slow", 21561 animateEasing: "swing", 21562 aspectRatio: false, 21563 autoHide: false, 21564 classes: { 21565 "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se" 21566 }, 21567 containment: false, 21568 ghost: false, 21569 grid: false, 21570 handles: "e,s,se", 21571 helper: false, 21572 maxHeight: null, 21573 maxWidth: null, 21574 minHeight: 10, 21575 minWidth: 10, 21576 21577 // See #7960 21578 zIndex: 90, 21579 21580 // Callbacks 21581 resize: null, 21582 start: null, 21583 stop: null 21584 }, 21585 21586 _num: function( value ) { 21587 return parseFloat( value ) || 0; 21588 }, 21589 21590 _isNumber: function( value ) { 21591 return !isNaN( parseFloat( value ) ); 21592 }, 21593 21594 _hasScroll: function( el, a ) { 21595 21596 var scroll, 21597 has = false, 21598 overflow = $( el ).css( "overflow" ); 21599 21600 if ( overflow === "hidden" ) { 21601 return false; 21602 } 21603 if ( overflow === "scroll" ) { 21604 return true; 21605 } 21606 21607 scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop"; 21608 21609 if ( el[ scroll ] > 0 ) { 21610 return true; 21611 } 21612 21613 // TODO: determine which cases actually cause this to happen 21614 // if the element doesn't have the scroll set, see if it's possible to 21615 // set the scroll 21616 try { 21617 el[ scroll ] = 1; 21618 has = ( el[ scroll ] > 0 ); 21619 el[ scroll ] = 0; 21620 } catch ( e ) { 21621 21622 // `el` might be a string, then setting `scroll` will throw 21623 // an error in strict mode; ignore it. 21624 } 21625 return has; 21626 }, 21627 21628 _create: function() { 21629 21630 var margins, 21631 o = this.options, 21632 that = this; 21633 this._addClass( "ui-resizable" ); 21634 21635 $.extend( this, { 21636 _aspectRatio: !!( o.aspectRatio ), 21637 aspectRatio: o.aspectRatio, 21638 originalElement: this.element, 21639 _proportionallyResizeElements: [], 21640 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null 21641 } ); 21642 21643 // Wrap the element if it cannot hold child nodes 21644 if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) { 21645 21646 this.element.wrap( 21647 $( "<div class='ui-wrapper'></div>" ).css( { 21648 overflow: "hidden", 21649 position: this.element.css( "position" ), 21650 width: this.element.outerWidth(), 21651 height: this.element.outerHeight(), 21652 top: this.element.css( "top" ), 21653 left: this.element.css( "left" ) 21654 } ) 21655 ); 21656 21657 this.element = this.element.parent().data( 21658 "ui-resizable", this.element.resizable( "instance" ) 21659 ); 21660 21661 this.elementIsWrapper = true; 21662 21663 margins = { 21664 marginTop: this.originalElement.css( "marginTop" ), 21665 marginRight: this.originalElement.css( "marginRight" ), 21666 marginBottom: this.originalElement.css( "marginBottom" ), 21667 marginLeft: this.originalElement.css( "marginLeft" ) 21668 }; 21669 21670 this.element.css( margins ); 21671 21672 // Support: Safari 21673 // Prevent Safari textarea resize 21674 this.originalResizeStyle = this.originalElement.css( "resize" ); 21675 this.originalElement.css( "resize", "none" ); 21676 21677 this._proportionallyResizeElements.push( this.originalElement.css( { 21678 position: "static", 21679 zoom: 1, 21680 display: "block" 21681 } ) ); 21682 21683 this._proportionallyResize(); 21684 } 21685 21686 this._setupHandles(); 21687 21688 if ( o.autoHide ) { 21689 $( this.element ) 21690 .on( "mouseenter", function() { 21691 if ( o.disabled ) { 21692 return; 21693 } 21694 that._removeClass( "ui-resizable-autohide" ); 21695 that._handles.show(); 21696 } ) 21697 .on( "mouseleave", function() { 21698 if ( o.disabled ) { 21699 return; 21700 } 21701 if ( !that.resizing ) { 21702 that._addClass( "ui-resizable-autohide" ); 21703 that._handles.hide(); 21704 } 21705 } ); 21706 } 21707 21708 this._mouseInit(); 21709 }, 21710 21711 _destroy: function() { 21712 21713 this._mouseDestroy(); 21714 this._addedHandles.remove(); 21715 21716 var wrapper, 21717 _destroy = function( exp ) { 21718 $( exp ) 21719 .removeData( "resizable" ) 21720 .removeData( "ui-resizable" ) 21721 .off( ".resizable" ); 21722 }; 21723 21724 // TODO: Unwrap at same DOM position 21725 if ( this.elementIsWrapper ) { 21726 _destroy( this.element ); 21727 wrapper = this.element; 21728 this.originalElement.css( { 21729 position: wrapper.css( "position" ), 21730 width: wrapper.outerWidth(), 21731 height: wrapper.outerHeight(), 21732 top: wrapper.css( "top" ), 21733 left: wrapper.css( "left" ) 21734 } ).insertAfter( wrapper ); 21735 wrapper.remove(); 21736 } 21737 21738 this.originalElement.css( "resize", this.originalResizeStyle ); 21739 _destroy( this.originalElement ); 21740 21741 return this; 21742 }, 21743 21744 _setOption: function( key, value ) { 21745 this._super( key, value ); 21746 21747 switch ( key ) { 21748 case "handles": 21749 this._removeHandles(); 21750 this._setupHandles(); 21751 break; 21752 case "aspectRatio": 21753 this._aspectRatio = !!value; 21754 break; 21755 default: 21756 break; 21757 } 21758 }, 21759 21760 _setupHandles: function() { 21761 var o = this.options, handle, i, n, hname, axis, that = this; 21762 this.handles = o.handles || 21763 ( !$( ".ui-resizable-handle", this.element ).length ? 21764 "e,s,se" : { 21765 n: ".ui-resizable-n", 21766 e: ".ui-resizable-e", 21767 s: ".ui-resizable-s", 21768 w: ".ui-resizable-w", 21769 se: ".ui-resizable-se", 21770 sw: ".ui-resizable-sw", 21771 ne: ".ui-resizable-ne", 21772 nw: ".ui-resizable-nw" 21773 } ); 21774 21775 this._handles = $(); 21776 this._addedHandles = $(); 21777 if ( this.handles.constructor === String ) { 21778 21779 if ( this.handles === "all" ) { 21780 this.handles = "n,e,s,w,se,sw,ne,nw"; 21781 } 21782 21783 n = this.handles.split( "," ); 21784 this.handles = {}; 21785 21786 for ( i = 0; i < n.length; i++ ) { 21787 21788 handle = String.prototype.trim.call( n[ i ] ); 21789 hname = "ui-resizable-" + handle; 21790 axis = $( "<div>" ); 21791 this._addClass( axis, "ui-resizable-handle " + hname ); 21792 21793 axis.css( { zIndex: o.zIndex } ); 21794 21795 this.handles[ handle ] = ".ui-resizable-" + handle; 21796 if ( !this.element.children( this.handles[ handle ] ).length ) { 21797 this.element.append( axis ); 21798 this._addedHandles = this._addedHandles.add( axis ); 21799 } 21800 } 21801 21802 } 21803 21804 this._renderAxis = function( target ) { 21805 21806 var i, axis, padPos, padWrapper; 21807 21808 target = target || this.element; 21809 21810 for ( i in this.handles ) { 21811 21812 if ( this.handles[ i ].constructor === String ) { 21813 this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show(); 21814 } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) { 21815 this.handles[ i ] = $( this.handles[ i ] ); 21816 this._on( this.handles[ i ], { "mousedown": that._mouseDown } ); 21817 } 21818 21819 if ( this.elementIsWrapper && 21820 this.originalElement[ 0 ] 21821 .nodeName 21822 .match( /^(textarea|input|select|button)$/i ) ) { 21823 axis = $( this.handles[ i ], this.element ); 21824 21825 padWrapper = /sw|ne|nw|se|n|s/.test( i ) ? 21826 axis.outerHeight() : 21827 axis.outerWidth(); 21828 21829 padPos = [ "padding", 21830 /ne|nw|n/.test( i ) ? "Top" : 21831 /se|sw|s/.test( i ) ? "Bottom" : 21832 /^e$/.test( i ) ? "Right" : "Left" ].join( "" ); 21833 21834 target.css( padPos, padWrapper ); 21835 21836 this._proportionallyResize(); 21837 } 21838 21839 this._handles = this._handles.add( this.handles[ i ] ); 21840 } 21841 }; 21842 21843 // TODO: make renderAxis a prototype function 21844 this._renderAxis( this.element ); 21845 21846 this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) ); 21847 this._handles.disableSelection(); 21848 21849 this._handles.on( "mouseover", function() { 21850 if ( !that.resizing ) { 21851 if ( this.className ) { 21852 axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i ); 21853 } 21854 that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se"; 21855 } 21856 } ); 21857 21858 if ( o.autoHide ) { 21859 this._handles.hide(); 21860 this._addClass( "ui-resizable-autohide" ); 21861 } 21862 }, 21863 21864 _removeHandles: function() { 21865 this._addedHandles.remove(); 21866 }, 21867 21868 _mouseCapture: function( event ) { 21869 var i, handle, 21870 capture = false; 21871 21872 for ( i in this.handles ) { 21873 handle = $( this.handles[ i ] )[ 0 ]; 21874 if ( handle === event.target || $.contains( handle, event.target ) ) { 21875 capture = true; 21876 } 21877 } 21878 21879 return !this.options.disabled && capture; 21880 }, 21881 21882 _mouseStart: function( event ) { 21883 21884 var curleft, curtop, cursor, calculatedSize, 21885 o = this.options, 21886 el = this.element; 21887 21888 this.resizing = true; 21889 21890 this._renderProxy(); 21891 21892 curleft = this._num( this.helper.css( "left" ) ); 21893 curtop = this._num( this.helper.css( "top" ) ); 21894 21895 if ( o.containment ) { 21896 curleft += $( o.containment ).scrollLeft() || 0; 21897 curtop += $( o.containment ).scrollTop() || 0; 21898 } 21899 21900 this.offset = this.helper.offset(); 21901 this.position = { left: curleft, top: curtop }; 21902 21903 if ( !this._helper ) { 21904 calculatedSize = this._calculateAdjustedElementDimensions( el ); 21905 } 21906 21907 this.size = this._helper ? { 21908 width: this.helper.width(), 21909 height: this.helper.height() 21910 } : { 21911 width: calculatedSize.width, 21912 height: calculatedSize.height 21913 }; 21914 21915 this.originalSize = this._helper ? { 21916 width: el.outerWidth(), 21917 height: el.outerHeight() 21918 } : { 21919 width: calculatedSize.width, 21920 height: calculatedSize.height 21921 }; 21922 21923 this.sizeDiff = { 21924 width: el.outerWidth() - el.width(), 21925 height: el.outerHeight() - el.height() 21926 }; 21927 21928 this.originalPosition = { left: curleft, top: curtop }; 21929 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 21930 21931 this.aspectRatio = ( typeof o.aspectRatio === "number" ) ? 21932 o.aspectRatio : 21933 ( ( this.originalSize.width / this.originalSize.height ) || 1 ); 21934 21935 cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" ); 21936 $( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor ); 21937 21938 this._addClass( "ui-resizable-resizing" ); 21939 this._propagate( "start", event ); 21940 return true; 21941 }, 21942 21943 _mouseDrag: function( event ) { 21944 21945 var data, props, 21946 smp = this.originalMousePosition, 21947 a = this.axis, 21948 dx = ( event.pageX - smp.left ) || 0, 21949 dy = ( event.pageY - smp.top ) || 0, 21950 trigger = this._change[ a ]; 21951 21952 this._updatePrevProperties(); 21953 21954 if ( !trigger ) { 21955 return false; 21956 } 21957 21958 data = trigger.apply( this, [ event, dx, dy ] ); 21959 21960 this._updateVirtualBoundaries( event.shiftKey ); 21961 if ( this._aspectRatio || event.shiftKey ) { 21962 data = this._updateRatio( data, event ); 21963 } 21964 21965 data = this._respectSize( data, event ); 21966 21967 this._updateCache( data ); 21968 21969 this._propagate( "resize", event ); 21970 21971 props = this._applyChanges(); 21972 21973 if ( !this._helper && this._proportionallyResizeElements.length ) { 21974 this._proportionallyResize(); 21975 } 21976 21977 if ( !$.isEmptyObject( props ) ) { 21978 this._updatePrevProperties(); 21979 this._trigger( "resize", event, this.ui() ); 21980 this._applyChanges(); 21981 } 21982 21983 return false; 21984 }, 21985 21986 _mouseStop: function( event ) { 21987 21988 this.resizing = false; 21989 var pr, ista, soffseth, soffsetw, s, left, top, 21990 o = this.options, that = this; 21991 21992 if ( this._helper ) { 21993 21994 pr = this._proportionallyResizeElements; 21995 ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ); 21996 soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height; 21997 soffsetw = ista ? 0 : that.sizeDiff.width; 21998 21999 s = { 22000 width: ( that.helper.width() - soffsetw ), 22001 height: ( that.helper.height() - soffseth ) 22002 }; 22003 left = ( parseFloat( that.element.css( "left" ) ) + 22004 ( that.position.left - that.originalPosition.left ) ) || null; 22005 top = ( parseFloat( that.element.css( "top" ) ) + 22006 ( that.position.top - that.originalPosition.top ) ) || null; 22007 22008 if ( !o.animate ) { 22009 this.element.css( $.extend( s, { top: top, left: left } ) ); 22010 } 22011 22012 that.helper.height( that.size.height ); 22013 that.helper.width( that.size.width ); 22014 22015 if ( this._helper && !o.animate ) { 22016 this._proportionallyResize(); 22017 } 22018 } 22019 22020 $( "body" ).css( "cursor", "auto" ); 22021 22022 this._removeClass( "ui-resizable-resizing" ); 22023 22024 this._propagate( "stop", event ); 22025 22026 if ( this._helper ) { 22027 this.helper.remove(); 22028 } 22029 22030 return false; 22031 22032 }, 22033 22034 _updatePrevProperties: function() { 22035 this.prevPosition = { 22036 top: this.position.top, 22037 left: this.position.left 22038 }; 22039 this.prevSize = { 22040 width: this.size.width, 22041 height: this.size.height 22042 }; 22043 }, 22044 22045 _applyChanges: function() { 22046 var props = {}; 22047 22048 if ( this.position.top !== this.prevPosition.top ) { 22049 props.top = this.position.top + "px"; 22050 } 22051 if ( this.position.left !== this.prevPosition.left ) { 22052 props.left = this.position.left + "px"; 22053 } 22054 22055 this.helper.css( props ); 22056 22057 if ( this.size.width !== this.prevSize.width ) { 22058 props.width = this.size.width + "px"; 22059 this.helper.width( props.width ); 22060 } 22061 if ( this.size.height !== this.prevSize.height ) { 22062 props.height = this.size.height + "px"; 22063 this.helper.height( props.height ); 22064 } 22065 22066 return props; 22067 }, 22068 22069 _updateVirtualBoundaries: function( forceAspectRatio ) { 22070 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, 22071 o = this.options; 22072 22073 b = { 22074 minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0, 22075 maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity, 22076 minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0, 22077 maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity 22078 }; 22079 22080 if ( this._aspectRatio || forceAspectRatio ) { 22081 pMinWidth = b.minHeight * this.aspectRatio; 22082 pMinHeight = b.minWidth / this.aspectRatio; 22083 pMaxWidth = b.maxHeight * this.aspectRatio; 22084 pMaxHeight = b.maxWidth / this.aspectRatio; 22085 22086 if ( pMinWidth > b.minWidth ) { 22087 b.minWidth = pMinWidth; 22088 } 22089 if ( pMinHeight > b.minHeight ) { 22090 b.minHeight = pMinHeight; 22091 } 22092 if ( pMaxWidth < b.maxWidth ) { 22093 b.maxWidth = pMaxWidth; 22094 } 22095 if ( pMaxHeight < b.maxHeight ) { 22096 b.maxHeight = pMaxHeight; 22097 } 22098 } 22099 this._vBoundaries = b; 22100 }, 22101 22102 _updateCache: function( data ) { 22103 this.offset = this.helper.offset(); 22104 if ( this._isNumber( data.left ) ) { 22105 this.position.left = data.left; 22106 } 22107 if ( this._isNumber( data.top ) ) { 22108 this.position.top = data.top; 22109 } 22110 if ( this._isNumber( data.height ) ) { 22111 this.size.height = data.height; 22112 } 22113 if ( this._isNumber( data.width ) ) { 22114 this.size.width = data.width; 22115 } 22116 }, 22117 22118 _updateRatio: function( data ) { 22119 22120 var cpos = this.position, 22121 csize = this.size, 22122 a = this.axis; 22123 22124 if ( this._isNumber( data.height ) ) { 22125 data.width = ( data.height * this.aspectRatio ); 22126 } else if ( this._isNumber( data.width ) ) { 22127 data.height = ( data.width / this.aspectRatio ); 22128 } 22129 22130 if ( a === "sw" ) { 22131 data.left = cpos.left + ( csize.width - data.width ); 22132 data.top = null; 22133 } 22134 if ( a === "nw" ) { 22135 data.top = cpos.top + ( csize.height - data.height ); 22136 data.left = cpos.left + ( csize.width - data.width ); 22137 } 22138 22139 return data; 22140 }, 22141 22142 _respectSize: function( data ) { 22143 22144 var o = this._vBoundaries, 22145 a = this.axis, 22146 ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ), 22147 ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ), 22148 isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ), 22149 isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ), 22150 dw = this.originalPosition.left + this.originalSize.width, 22151 dh = this.originalPosition.top + this.originalSize.height, 22152 cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a ); 22153 if ( isminw ) { 22154 data.width = o.minWidth; 22155 } 22156 if ( isminh ) { 22157 data.height = o.minHeight; 22158 } 22159 if ( ismaxw ) { 22160 data.width = o.maxWidth; 22161 } 22162 if ( ismaxh ) { 22163 data.height = o.maxHeight; 22164 } 22165 22166 if ( isminw && cw ) { 22167 data.left = dw - o.minWidth; 22168 } 22169 if ( ismaxw && cw ) { 22170 data.left = dw - o.maxWidth; 22171 } 22172 if ( isminh && ch ) { 22173 data.top = dh - o.minHeight; 22174 } 22175 if ( ismaxh && ch ) { 22176 data.top = dh - o.maxHeight; 22177 } 22178 22179 // Fixing jump error on top/left - bug #2330 22180 if ( !data.width && !data.height && !data.left && data.top ) { 22181 data.top = null; 22182 } else if ( !data.width && !data.height && !data.top && data.left ) { 22183 data.left = null; 22184 } 22185 22186 return data; 22187 }, 22188 22189 _getPaddingPlusBorderDimensions: function( element ) { 22190 var i = 0, 22191 widths = [], 22192 borders = [ 22193 element.css( "borderTopWidth" ), 22194 element.css( "borderRightWidth" ), 22195 element.css( "borderBottomWidth" ), 22196 element.css( "borderLeftWidth" ) 22197 ], 22198 paddings = [ 22199 element.css( "paddingTop" ), 22200 element.css( "paddingRight" ), 22201 element.css( "paddingBottom" ), 22202 element.css( "paddingLeft" ) 22203 ]; 22204 22205 for ( ; i < 4; i++ ) { 22206 widths[ i ] = ( parseFloat( borders[ i ] ) || 0 ); 22207 widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 ); 22208 } 22209 22210 return { 22211 height: widths[ 0 ] + widths[ 2 ], 22212 width: widths[ 1 ] + widths[ 3 ] 22213 }; 22214 }, 22215 22216 _calculateAdjustedElementDimensions: function( element ) { 22217 var elWidth, elHeight, paddingBorder, 22218 ce = element.get( 0 ); 22219 22220 if ( element.css( "box-sizing" ) !== "content-box" || 22221 ( !this._hasScroll( ce ) && !this._hasScroll( ce, "left" ) ) ) { 22222 return { 22223 height: parseFloat( element.css( "height" ) ), 22224 width: parseFloat( element.css( "width" ) ) 22225 }; 22226 } 22227 22228 // Check if CSS inline styles are set and use those (usually from previous resizes) 22229 elWidth = parseFloat( ce.style.width ); 22230 elHeight = parseFloat( ce.style.height ); 22231 22232 paddingBorder = this._getPaddingPlusBorderDimensions( element ); 22233 elWidth = isNaN( elWidth ) ? 22234 this._getElementTheoreticalSize( element, paddingBorder, "width" ) : 22235 elWidth; 22236 elHeight = isNaN( elHeight ) ? 22237 this._getElementTheoreticalSize( element, paddingBorder, "height" ) : 22238 elHeight; 22239 22240 return { 22241 height: elHeight, 22242 width: elWidth 22243 }; 22244 }, 22245 22246 _getElementTheoreticalSize: function( element, extraSize, dimension ) { 22247 22248 // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border 22249 var size = Math.max( 0, Math.ceil( 22250 element.get( 0 )[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - 22251 extraSize[ dimension ] - 22252 0.5 22253 22254 // If offsetWidth/offsetHeight is unknown, then we can't determine theoretical size. 22255 // Use an explicit zero to avoid NaN. 22256 // See https://github.com/jquery/jquery/issues/3964 22257 ) ) || 0; 22258 22259 return size; 22260 }, 22261 22262 _proportionallyResize: function() { 22263 22264 if ( !this._proportionallyResizeElements.length ) { 22265 return; 22266 } 22267 22268 var prel, 22269 i = 0, 22270 element = this.helper || this.element; 22271 22272 for ( ; i < this._proportionallyResizeElements.length; i++ ) { 22273 22274 prel = this._proportionallyResizeElements[ i ]; 22275 22276 // TODO: Seems like a bug to cache this.outerDimensions 22277 // considering that we are in a loop. 22278 if ( !this.outerDimensions ) { 22279 this.outerDimensions = this._getPaddingPlusBorderDimensions( prel ); 22280 } 22281 22282 prel.css( { 22283 height: ( element.height() - this.outerDimensions.height ) || 0, 22284 width: ( element.width() - this.outerDimensions.width ) || 0 22285 } ); 22286 22287 } 22288 22289 }, 22290 22291 _renderProxy: function() { 22292 22293 var el = this.element, o = this.options; 22294 this.elementOffset = el.offset(); 22295 22296 if ( this._helper ) { 22297 22298 this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } ); 22299 22300 this._addClass( this.helper, this._helper ); 22301 this.helper.css( { 22302 width: this.element.outerWidth(), 22303 height: this.element.outerHeight(), 22304 position: "absolute", 22305 left: this.elementOffset.left + "px", 22306 top: this.elementOffset.top + "px", 22307 zIndex: ++o.zIndex //TODO: Don't modify option 22308 } ); 22309 22310 this.helper 22311 .appendTo( "body" ) 22312 .disableSelection(); 22313 22314 } else { 22315 this.helper = this.element; 22316 } 22317 22318 }, 22319 22320 _change: { 22321 e: function( event, dx ) { 22322 return { width: this.originalSize.width + dx }; 22323 }, 22324 w: function( event, dx ) { 22325 var cs = this.originalSize, sp = this.originalPosition; 22326 return { left: sp.left + dx, width: cs.width - dx }; 22327 }, 22328 n: function( event, dx, dy ) { 22329 var cs = this.originalSize, sp = this.originalPosition; 22330 return { top: sp.top + dy, height: cs.height - dy }; 22331 }, 22332 s: function( event, dx, dy ) { 22333 return { height: this.originalSize.height + dy }; 22334 }, 22335 se: function( event, dx, dy ) { 22336 return $.extend( this._change.s.apply( this, arguments ), 22337 this._change.e.apply( this, [ event, dx, dy ] ) ); 22338 }, 22339 sw: function( event, dx, dy ) { 22340 return $.extend( this._change.s.apply( this, arguments ), 22341 this._change.w.apply( this, [ event, dx, dy ] ) ); 22342 }, 22343 ne: function( event, dx, dy ) { 22344 return $.extend( this._change.n.apply( this, arguments ), 22345 this._change.e.apply( this, [ event, dx, dy ] ) ); 22346 }, 22347 nw: function( event, dx, dy ) { 22348 return $.extend( this._change.n.apply( this, arguments ), 22349 this._change.w.apply( this, [ event, dx, dy ] ) ); 22350 } 22351 }, 22352 22353 _propagate: function( n, event ) { 22354 $.ui.plugin.call( this, n, [ event, this.ui() ] ); 22355 if ( n !== "resize" ) { 22356 this._trigger( n, event, this.ui() ); 22357 } 22358 }, 22359 22360 plugins: {}, 22361 22362 ui: function() { 22363 return { 22364 originalElement: this.originalElement, 22365 element: this.element, 22366 helper: this.helper, 22367 position: this.position, 22368 size: this.size, 22369 originalSize: this.originalSize, 22370 originalPosition: this.originalPosition 22371 }; 22372 } 22373 22374} ); 22375 22376/* 22377 * Resizable Extensions 22378 */ 22379 22380$.ui.plugin.add( "resizable", "animate", { 22381 22382 stop: function( event ) { 22383 var that = $( this ).resizable( "instance" ), 22384 o = that.options, 22385 pr = that._proportionallyResizeElements, 22386 ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ), 22387 soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height, 22388 soffsetw = ista ? 0 : that.sizeDiff.width, 22389 style = { 22390 width: ( that.size.width - soffsetw ), 22391 height: ( that.size.height - soffseth ) 22392 }, 22393 left = ( parseFloat( that.element.css( "left" ) ) + 22394 ( that.position.left - that.originalPosition.left ) ) || null, 22395 top = ( parseFloat( that.element.css( "top" ) ) + 22396 ( that.position.top - that.originalPosition.top ) ) || null; 22397 22398 that.element.animate( 22399 $.extend( style, top && left ? { top: top, left: left } : {} ), { 22400 duration: o.animateDuration, 22401 easing: o.animateEasing, 22402 step: function() { 22403 22404 var data = { 22405 width: parseFloat( that.element.css( "width" ) ), 22406 height: parseFloat( that.element.css( "height" ) ), 22407 top: parseFloat( that.element.css( "top" ) ), 22408 left: parseFloat( that.element.css( "left" ) ) 22409 }; 22410 22411 if ( pr && pr.length ) { 22412 $( pr[ 0 ] ).css( { width: data.width, height: data.height } ); 22413 } 22414 22415 // Propagating resize, and updating values for each animation step 22416 that._updateCache( data ); 22417 that._propagate( "resize", event ); 22418 22419 } 22420 } 22421 ); 22422 } 22423 22424} ); 22425 22426$.ui.plugin.add( "resizable", "containment", { 22427 22428 start: function() { 22429 var element, p, co, ch, cw, width, height, 22430 that = $( this ).resizable( "instance" ), 22431 o = that.options, 22432 el = that.element, 22433 oc = o.containment, 22434 ce = ( oc instanceof $ ) ? 22435 oc.get( 0 ) : 22436 ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc; 22437 22438 if ( !ce ) { 22439 return; 22440 } 22441 22442 that.containerElement = $( ce ); 22443 22444 if ( /document/.test( oc ) || oc === document ) { 22445 that.containerOffset = { 22446 left: 0, 22447 top: 0 22448 }; 22449 that.containerPosition = { 22450 left: 0, 22451 top: 0 22452 }; 22453 22454 that.parentData = { 22455 element: $( document ), 22456 left: 0, 22457 top: 0, 22458 width: $( document ).width(), 22459 height: $( document ).height() || document.body.parentNode.scrollHeight 22460 }; 22461 } else { 22462 element = $( ce ); 22463 p = []; 22464 $( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) { 22465 p[ i ] = that._num( element.css( "padding" + name ) ); 22466 } ); 22467 22468 that.containerOffset = element.offset(); 22469 that.containerPosition = element.position(); 22470 that.containerSize = { 22471 height: ( element.innerHeight() - p[ 3 ] ), 22472 width: ( element.innerWidth() - p[ 1 ] ) 22473 }; 22474 22475 co = that.containerOffset; 22476 ch = that.containerSize.height; 22477 cw = that.containerSize.width; 22478 width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw ); 22479 height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch ); 22480 22481 that.parentData = { 22482 element: ce, 22483 left: co.left, 22484 top: co.top, 22485 width: width, 22486 height: height 22487 }; 22488 } 22489 }, 22490 22491 resize: function( event ) { 22492 var woset, hoset, isParent, isOffsetRelative, 22493 that = $( this ).resizable( "instance" ), 22494 o = that.options, 22495 co = that.containerOffset, 22496 cp = that.position, 22497 pRatio = that._aspectRatio || event.shiftKey, 22498 cop = { 22499 top: 0, 22500 left: 0 22501 }, 22502 ce = that.containerElement, 22503 continueResize = true; 22504 22505 if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) { 22506 cop = co; 22507 } 22508 22509 if ( cp.left < ( that._helper ? co.left : 0 ) ) { 22510 that.size.width = that.size.width + 22511 ( that._helper ? 22512 ( that.position.left - co.left ) : 22513 ( that.position.left - cop.left ) ); 22514 22515 if ( pRatio ) { 22516 that.size.height = that.size.width / that.aspectRatio; 22517 continueResize = false; 22518 } 22519 that.position.left = o.helper ? co.left : 0; 22520 } 22521 22522 if ( cp.top < ( that._helper ? co.top : 0 ) ) { 22523 that.size.height = that.size.height + 22524 ( that._helper ? 22525 ( that.position.top - co.top ) : 22526 that.position.top ); 22527 22528 if ( pRatio ) { 22529 that.size.width = that.size.height * that.aspectRatio; 22530 continueResize = false; 22531 } 22532 that.position.top = that._helper ? co.top : 0; 22533 } 22534 22535 isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 ); 22536 isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) ); 22537 22538 if ( isParent && isOffsetRelative ) { 22539 that.offset.left = that.parentData.left + that.position.left; 22540 that.offset.top = that.parentData.top + that.position.top; 22541 } else { 22542 that.offset.left = that.element.offset().left; 22543 that.offset.top = that.element.offset().top; 22544 } 22545 22546 woset = Math.abs( that.sizeDiff.width + 22547 ( that._helper ? 22548 that.offset.left - cop.left : 22549 ( that.offset.left - co.left ) ) ); 22550 22551 hoset = Math.abs( that.sizeDiff.height + 22552 ( that._helper ? 22553 that.offset.top - cop.top : 22554 ( that.offset.top - co.top ) ) ); 22555 22556 if ( woset + that.size.width >= that.parentData.width ) { 22557 that.size.width = that.parentData.width - woset; 22558 if ( pRatio ) { 22559 that.size.height = that.size.width / that.aspectRatio; 22560 continueResize = false; 22561 } 22562 } 22563 22564 if ( hoset + that.size.height >= that.parentData.height ) { 22565 that.size.height = that.parentData.height - hoset; 22566 if ( pRatio ) { 22567 that.size.width = that.size.height * that.aspectRatio; 22568 continueResize = false; 22569 } 22570 } 22571 22572 if ( !continueResize ) { 22573 that.position.left = that.prevPosition.left; 22574 that.position.top = that.prevPosition.top; 22575 that.size.width = that.prevSize.width; 22576 that.size.height = that.prevSize.height; 22577 } 22578 }, 22579 22580 stop: function() { 22581 var that = $( this ).resizable( "instance" ), 22582 o = that.options, 22583 co = that.containerOffset, 22584 cop = that.containerPosition, 22585 ce = that.containerElement, 22586 helper = $( that.helper ), 22587 ho = helper.offset(), 22588 w = helper.outerWidth() - that.sizeDiff.width, 22589 h = helper.outerHeight() - that.sizeDiff.height; 22590 22591 if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) { 22592 $( this ).css( { 22593 left: ho.left - cop.left - co.left, 22594 width: w, 22595 height: h 22596 } ); 22597 } 22598 22599 if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) { 22600 $( this ).css( { 22601 left: ho.left - cop.left - co.left, 22602 width: w, 22603 height: h 22604 } ); 22605 } 22606 } 22607} ); 22608 22609$.ui.plugin.add( "resizable", "alsoResize", { 22610 22611 start: function() { 22612 var that = $( this ).resizable( "instance" ), 22613 o = that.options; 22614 22615 $( o.alsoResize ).each( function() { 22616 var el = $( this ), 22617 elSize = that._calculateAdjustedElementDimensions( el ); 22618 22619 el.data( "ui-resizable-alsoresize", { 22620 width: elSize.width, height: elSize.height, 22621 left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) ) 22622 } ); 22623 } ); 22624 }, 22625 22626 resize: function( event, ui ) { 22627 var that = $( this ).resizable( "instance" ), 22628 o = that.options, 22629 os = that.originalSize, 22630 op = that.originalPosition, 22631 delta = { 22632 height: ( that.size.height - os.height ) || 0, 22633 width: ( that.size.width - os.width ) || 0, 22634 top: ( that.position.top - op.top ) || 0, 22635 left: ( that.position.left - op.left ) || 0 22636 }; 22637 22638 $( o.alsoResize ).each( function() { 22639 var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {}, 22640 css = el.parents( ui.originalElement[ 0 ] ).length ? 22641 [ "width", "height" ] : 22642 [ "width", "height", "top", "left" ]; 22643 22644 $.each( css, function( i, prop ) { 22645 var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 ); 22646 if ( sum && sum >= 0 ) { 22647 style[ prop ] = sum || null; 22648 } 22649 } ); 22650 22651 el.css( style ); 22652 } ); 22653 }, 22654 22655 stop: function() { 22656 $( this ).removeData( "ui-resizable-alsoresize" ); 22657 } 22658} ); 22659 22660$.ui.plugin.add( "resizable", "ghost", { 22661 22662 start: function() { 22663 22664 var that = $( this ).resizable( "instance" ), cs = that.size; 22665 22666 that.ghost = that.originalElement.clone(); 22667 that.ghost.css( { 22668 opacity: 0.25, 22669 display: "block", 22670 position: "relative", 22671 height: cs.height, 22672 width: cs.width, 22673 margin: 0, 22674 left: 0, 22675 top: 0 22676 } ); 22677 22678 that._addClass( that.ghost, "ui-resizable-ghost" ); 22679 22680 // DEPRECATED 22681 // TODO: remove after 1.12 22682 if ( $.uiBackCompat === true && typeof that.options.ghost === "string" ) { 22683 22684 // Ghost option 22685 that.ghost.addClass( this.options.ghost ); 22686 } 22687 22688 that.ghost.appendTo( that.helper ); 22689 22690 }, 22691 22692 resize: function() { 22693 var that = $( this ).resizable( "instance" ); 22694 if ( that.ghost ) { 22695 that.ghost.css( { 22696 position: "relative", 22697 height: that.size.height, 22698 width: that.size.width 22699 } ); 22700 } 22701 }, 22702 22703 stop: function() { 22704 var that = $( this ).resizable( "instance" ); 22705 if ( that.ghost && that.helper ) { 22706 that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) ); 22707 } 22708 } 22709 22710} ); 22711 22712$.ui.plugin.add( "resizable", "grid", { 22713 22714 resize: function() { 22715 var outerDimensions, 22716 that = $( this ).resizable( "instance" ), 22717 o = that.options, 22718 cs = that.size, 22719 os = that.originalSize, 22720 op = that.originalPosition, 22721 a = that.axis, 22722 grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid, 22723 gridX = ( grid[ 0 ] || 1 ), 22724 gridY = ( grid[ 1 ] || 1 ), 22725 ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX, 22726 oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY, 22727 newWidth = os.width + ox, 22728 newHeight = os.height + oy, 22729 isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ), 22730 isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ), 22731 isMinWidth = o.minWidth && ( o.minWidth > newWidth ), 22732 isMinHeight = o.minHeight && ( o.minHeight > newHeight ); 22733 22734 o.grid = grid; 22735 22736 if ( isMinWidth ) { 22737 newWidth += gridX; 22738 } 22739 if ( isMinHeight ) { 22740 newHeight += gridY; 22741 } 22742 if ( isMaxWidth ) { 22743 newWidth -= gridX; 22744 } 22745 if ( isMaxHeight ) { 22746 newHeight -= gridY; 22747 } 22748 22749 if ( /^(se|s|e)$/.test( a ) ) { 22750 that.size.width = newWidth; 22751 that.size.height = newHeight; 22752 } else if ( /^(ne)$/.test( a ) ) { 22753 that.size.width = newWidth; 22754 that.size.height = newHeight; 22755 that.position.top = op.top - oy; 22756 } else if ( /^(sw)$/.test( a ) ) { 22757 that.size.width = newWidth; 22758 that.size.height = newHeight; 22759 that.position.left = op.left - ox; 22760 } else { 22761 if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) { 22762 outerDimensions = that._getPaddingPlusBorderDimensions( this ); 22763 } 22764 22765 if ( newHeight - gridY > 0 ) { 22766 that.size.height = newHeight; 22767 that.position.top = op.top - oy; 22768 } else { 22769 newHeight = gridY - outerDimensions.height; 22770 that.size.height = newHeight; 22771 that.position.top = op.top + os.height - newHeight; 22772 } 22773 if ( newWidth - gridX > 0 ) { 22774 that.size.width = newWidth; 22775 that.position.left = op.left - ox; 22776 } else { 22777 newWidth = gridX - outerDimensions.width; 22778 that.size.width = newWidth; 22779 that.position.left = op.left + os.width - newWidth; 22780 } 22781 } 22782 } 22783 22784} ); 22785 22786var widgetsResizable = $.ui.resizable; 22787 22788 22789/*! 22790 * jQuery UI Dialog 1.14.1 22791 * https://jqueryui.com 22792 * 22793 * Copyright OpenJS Foundation and other contributors 22794 * Released under the MIT license. 22795 * https://jquery.org/license 22796 */ 22797 22798//>>label: Dialog 22799//>>group: Widgets 22800//>>description: Displays customizable dialog windows. 22801//>>docs: https://api.jqueryui.com/dialog/ 22802//>>demos: https://jqueryui.com/dialog/ 22803//>>css.structure: ../../themes/base/core.css 22804//>>css.structure: ../../themes/base/dialog.css 22805//>>css.theme: ../../themes/base/theme.css 22806 22807 22808$.widget( "ui.dialog", { 22809 version: "1.14.1", 22810 options: { 22811 appendTo: "body", 22812 autoOpen: true, 22813 buttons: [], 22814 classes: { 22815 "ui-dialog": "ui-corner-all", 22816 "ui-dialog-titlebar": "ui-corner-all" 22817 }, 22818 closeOnEscape: true, 22819 closeText: "Close", 22820 draggable: true, 22821 hide: null, 22822 height: "auto", 22823 maxHeight: null, 22824 maxWidth: null, 22825 minHeight: 150, 22826 minWidth: 150, 22827 modal: false, 22828 position: { 22829 my: "center", 22830 at: "center", 22831 of: window, 22832 collision: "fit", 22833 22834 // Ensure the titlebar is always visible 22835 using: function( pos ) { 22836 var topOffset = $( this ).css( pos ).offset().top; 22837 if ( topOffset < 0 ) { 22838 $( this ).css( "top", pos.top - topOffset ); 22839 } 22840 } 22841 }, 22842 resizable: true, 22843 show: null, 22844 title: null, 22845 uiDialogTitleHeadingLevel: 0, 22846 width: 300, 22847 22848 // Callbacks 22849 beforeClose: null, 22850 close: null, 22851 drag: null, 22852 dragStart: null, 22853 dragStop: null, 22854 focus: null, 22855 open: null, 22856 resize: null, 22857 resizeStart: null, 22858 resizeStop: null 22859 }, 22860 22861 sizeRelatedOptions: { 22862 buttons: true, 22863 height: true, 22864 maxHeight: true, 22865 maxWidth: true, 22866 minHeight: true, 22867 minWidth: true, 22868 width: true 22869 }, 22870 22871 resizableRelatedOptions: { 22872 maxHeight: true, 22873 maxWidth: true, 22874 minHeight: true, 22875 minWidth: true 22876 }, 22877 22878 _create: function() { 22879 this.originalCss = { 22880 display: this.element[ 0 ].style.display, 22881 width: this.element[ 0 ].style.width, 22882 minHeight: this.element[ 0 ].style.minHeight, 22883 maxHeight: this.element[ 0 ].style.maxHeight, 22884 height: this.element[ 0 ].style.height 22885 }; 22886 this.originalPosition = { 22887 parent: this.element.parent(), 22888 index: this.element.parent().children().index( this.element ) 22889 }; 22890 this.originalTitle = this.element.attr( "title" ); 22891 if ( this.options.title == null && this.originalTitle != null ) { 22892 this.options.title = this.originalTitle; 22893 } 22894 22895 // Dialogs can't be disabled 22896 if ( this.options.disabled ) { 22897 this.options.disabled = false; 22898 } 22899 22900 this._createWrapper(); 22901 22902 this.element 22903 .show() 22904 .removeAttr( "title" ) 22905 .appendTo( this.uiDialog ); 22906 22907 this._addClass( "ui-dialog-content", "ui-widget-content" ); 22908 22909 this._createTitlebar(); 22910 this._createButtonPane(); 22911 22912 if ( this.options.draggable && $.fn.draggable ) { 22913 this._makeDraggable(); 22914 } 22915 if ( this.options.resizable && $.fn.resizable ) { 22916 this._makeResizable(); 22917 } 22918 22919 this._isOpen = false; 22920 22921 this._trackFocus(); 22922 }, 22923 22924 _init: function() { 22925 if ( this.options.autoOpen ) { 22926 this.open(); 22927 } 22928 }, 22929 22930 _appendTo: function() { 22931 var element = this.options.appendTo; 22932 if ( element && ( element.jquery || element.nodeType ) ) { 22933 return $( element ); 22934 } 22935 return this.document.find( element || "body" ).eq( 0 ); 22936 }, 22937 22938 _destroy: function() { 22939 var next, 22940 originalPosition = this.originalPosition; 22941 22942 this._untrackInstance(); 22943 this._destroyOverlay(); 22944 22945 this.element 22946 .removeUniqueId() 22947 .css( this.originalCss ) 22948 22949 // Without detaching first, the following becomes really slow 22950 .detach(); 22951 22952 this.uiDialog.remove(); 22953 22954 if ( this.originalTitle ) { 22955 this.element.attr( "title", this.originalTitle ); 22956 } 22957 22958 next = originalPosition.parent.children().eq( originalPosition.index ); 22959 22960 // Don't try to place the dialog next to itself (#8613) 22961 if ( next.length && next[ 0 ] !== this.element[ 0 ] ) { 22962 next.before( this.element ); 22963 } else { 22964 originalPosition.parent.append( this.element ); 22965 } 22966 }, 22967 22968 widget: function() { 22969 return this.uiDialog; 22970 }, 22971 22972 disable: $.noop, 22973 enable: $.noop, 22974 22975 close: function( event ) { 22976 var that = this; 22977 22978 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { 22979 return; 22980 } 22981 22982 this._isOpen = false; 22983 this._focusedElement = null; 22984 this._destroyOverlay(); 22985 this._untrackInstance(); 22986 22987 if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) { 22988 22989 // Hiding a focused element doesn't trigger blur in WebKit 22990 // so in case we have nothing to focus on, explicitly blur the active element 22991 // https://bugs.webkit.org/show_bug.cgi?id=47182 22992 $( this.document[ 0 ].activeElement ).trigger( "blur" ); 22993 } 22994 22995 this._hide( this.uiDialog, this.options.hide, function() { 22996 that._trigger( "close", event ); 22997 } ); 22998 }, 22999 23000 isOpen: function() { 23001 return this._isOpen; 23002 }, 23003 23004 moveToTop: function() { 23005 this._moveToTop(); 23006 }, 23007 23008 _moveToTop: function( event, silent ) { 23009 var moved = false, 23010 zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() { 23011 return +$( this ).css( "z-index" ); 23012 } ).get(), 23013 zIndexMax = Math.max.apply( null, zIndices ); 23014 23015 if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) { 23016 this.uiDialog.css( "z-index", zIndexMax + 1 ); 23017 moved = true; 23018 } 23019 23020 if ( moved && !silent ) { 23021 this._trigger( "focus", event ); 23022 } 23023 return moved; 23024 }, 23025 23026 open: function() { 23027 var that = this; 23028 if ( this._isOpen ) { 23029 if ( this._moveToTop() ) { 23030 this._focusTabbable(); 23031 } 23032 return; 23033 } 23034 23035 this._isOpen = true; 23036 this.opener = $( this.document[ 0 ].activeElement ); 23037 23038 this._size(); 23039 this._position(); 23040 this._createOverlay(); 23041 this._moveToTop( null, true ); 23042 23043 // Ensure the overlay is moved to the top with the dialog, but only when 23044 // opening. The overlay shouldn't move after the dialog is open so that 23045 // modeless dialogs opened after the modal dialog stack properly. 23046 if ( this.overlay ) { 23047 this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 ); 23048 } 23049 23050 this._show( this.uiDialog, this.options.show, function() { 23051 that._focusTabbable(); 23052 that._trigger( "focus" ); 23053 } ); 23054 23055 // Track the dialog immediately upon opening in case a focus event 23056 // somehow occurs outside of the dialog before an element inside the 23057 // dialog is focused (#10152) 23058 this._makeFocusTarget(); 23059 23060 this._trigger( "open" ); 23061 }, 23062 23063 _focusTabbable: function() { 23064 23065 // Set focus to the first match: 23066 // 1. An element that was focused previously 23067 // 2. First element inside the dialog matching [autofocus] 23068 // 3. Tabbable element inside the content element 23069 // 4. Tabbable element inside the buttonpane 23070 // 5. The close button 23071 // 6. The dialog itself 23072 var hasFocus = this._focusedElement; 23073 if ( !hasFocus ) { 23074 hasFocus = this.element.find( "[autofocus]" ); 23075 } 23076 if ( !hasFocus.length ) { 23077 hasFocus = this.element.find( ":tabbable" ); 23078 } 23079 if ( !hasFocus.length ) { 23080 hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); 23081 } 23082 if ( !hasFocus.length ) { 23083 hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" ); 23084 } 23085 if ( !hasFocus.length ) { 23086 hasFocus = this.uiDialog; 23087 } 23088 hasFocus.eq( 0 ).trigger( "focus" ); 23089 }, 23090 23091 _restoreTabbableFocus: function() { 23092 var activeElement = this.document[ 0 ].activeElement, 23093 isActive = this.uiDialog[ 0 ] === activeElement || 23094 $.contains( this.uiDialog[ 0 ], activeElement ); 23095 if ( !isActive ) { 23096 this._focusTabbable(); 23097 } 23098 }, 23099 23100 _keepFocus: function( event ) { 23101 event.preventDefault(); 23102 this._restoreTabbableFocus(); 23103 }, 23104 23105 _createWrapper: function() { 23106 this.uiDialog = $( "<div>" ) 23107 .hide() 23108 .attr( { 23109 23110 // Setting tabIndex makes the div focusable 23111 tabIndex: -1, 23112 role: "dialog", 23113 "aria-modal": this.options.modal ? "true" : null 23114 } ) 23115 .appendTo( this._appendTo() ); 23116 23117 this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" ); 23118 this._on( this.uiDialog, { 23119 keydown: function( event ) { 23120 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 23121 event.keyCode === $.ui.keyCode.ESCAPE ) { 23122 event.preventDefault(); 23123 this.close( event ); 23124 return; 23125 } 23126 23127 // Prevent tabbing out of dialogs 23128 if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) { 23129 return; 23130 } 23131 var tabbables = this.uiDialog.find( ":tabbable" ), 23132 first = tabbables.first(), 23133 last = tabbables.last(); 23134 23135 if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) && 23136 !event.shiftKey ) { 23137 this._delay( function() { 23138 first.trigger( "focus" ); 23139 } ); 23140 event.preventDefault(); 23141 } else if ( ( event.target === first[ 0 ] || 23142 event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) { 23143 this._delay( function() { 23144 last.trigger( "focus" ); 23145 } ); 23146 event.preventDefault(); 23147 } 23148 }, 23149 mousedown: function( event ) { 23150 if ( this._moveToTop( event ) ) { 23151 this._focusTabbable(); 23152 } 23153 } 23154 } ); 23155 23156 // We assume that any existing aria-describedby attribute means 23157 // that the dialog content is marked up properly 23158 // otherwise we brute force the content as the description 23159 if ( !this.element.find( "[aria-describedby]" ).length ) { 23160 this.uiDialog.attr( { 23161 "aria-describedby": this.element.uniqueId().attr( "id" ) 23162 } ); 23163 } 23164 }, 23165 23166 _createTitlebar: function() { 23167 var uiDialogTitle; 23168 23169 this.uiDialogTitlebar = $( "<div>" ); 23170 this._addClass( this.uiDialogTitlebar, 23171 "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" ); 23172 this._on( this.uiDialogTitlebar, { 23173 mousedown: function( event ) { 23174 23175 // Don't prevent click on close button (#8838) 23176 // Focusing a dialog that is partially scrolled out of view 23177 // causes the browser to scroll it into view, preventing the click event 23178 if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) { 23179 23180 // Dialog isn't getting focus when dragging (#8063) 23181 this.uiDialog.trigger( "focus" ); 23182 } 23183 } 23184 } ); 23185 23186 this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) 23187 .button( { 23188 label: $( "<a>" ).text( this.options.closeText ).html(), 23189 icon: "ui-icon-closethick", 23190 showLabel: false 23191 } ) 23192 .appendTo( this.uiDialogTitlebar ); 23193 23194 this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" ); 23195 this._on( this.uiDialogTitlebarClose, { 23196 click: function( event ) { 23197 event.preventDefault(); 23198 this.close( event ); 23199 } 23200 } ); 23201 23202 var uiDialogHeadingLevel = Number.isInteger( this.options.uiDialogTitleHeadingLevel ) && 23203 this.options.uiDialogTitleHeadingLevel > 0 && 23204 this.options.uiDialogTitleHeadingLevel <= 6 ? 23205 "h" + this.options.uiDialogTitleHeadingLevel : "span"; 23206 23207 uiDialogTitle = $( "<" + uiDialogHeadingLevel + ">" ) 23208 .uniqueId().prependTo( this.uiDialogTitlebar ); 23209 this._addClass( uiDialogTitle, "ui-dialog-title" ); 23210 this._title( uiDialogTitle ); 23211 23212 this.uiDialogTitlebar.prependTo( this.uiDialog ); 23213 23214 this.uiDialog.attr( { 23215 "aria-labelledby": uiDialogTitle.attr( "id" ) 23216 } ); 23217 }, 23218 23219 _title: function( title ) { 23220 if ( this.options.title ) { 23221 title.text( this.options.title ); 23222 } else { 23223 title.html( " " ); 23224 } 23225 }, 23226 23227 _createButtonPane: function() { 23228 this.uiDialogButtonPane = $( "<div>" ); 23229 this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane", 23230 "ui-widget-content ui-helper-clearfix" ); 23231 23232 this.uiButtonSet = $( "<div>" ) 23233 .appendTo( this.uiDialogButtonPane ); 23234 this._addClass( this.uiButtonSet, "ui-dialog-buttonset" ); 23235 23236 this._createButtons(); 23237 }, 23238 23239 _createButtons: function() { 23240 var that = this, 23241 buttons = this.options.buttons; 23242 23243 // If we already have a button pane, remove it 23244 this.uiDialogButtonPane.remove(); 23245 this.uiButtonSet.empty(); 23246 23247 if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) { 23248 this._removeClass( this.uiDialog, "ui-dialog-buttons" ); 23249 return; 23250 } 23251 23252 $.each( buttons, function( name, props ) { 23253 var click, buttonOptions; 23254 props = typeof props === "function" ? 23255 { click: props, text: name } : 23256 props; 23257 23258 // Default to a non-submitting button 23259 props = $.extend( { type: "button" }, props ); 23260 23261 // Change the context for the click callback to be the main element 23262 click = props.click; 23263 buttonOptions = { 23264 icon: props.icon, 23265 iconPosition: props.iconPosition, 23266 showLabel: props.showLabel, 23267 23268 // Deprecated options 23269 icons: props.icons, 23270 text: props.text 23271 }; 23272 23273 delete props.click; 23274 delete props.icon; 23275 delete props.iconPosition; 23276 delete props.showLabel; 23277 23278 // Deprecated options 23279 delete props.icons; 23280 if ( typeof props.text === "boolean" ) { 23281 delete props.text; 23282 } 23283 23284 $( "<button></button>", props ) 23285 .button( buttonOptions ) 23286 .appendTo( that.uiButtonSet ) 23287 .on( "click", function() { 23288 click.apply( that.element[ 0 ], arguments ); 23289 } ); 23290 } ); 23291 this._addClass( this.uiDialog, "ui-dialog-buttons" ); 23292 this.uiDialogButtonPane.appendTo( this.uiDialog ); 23293 }, 23294 23295 _makeDraggable: function() { 23296 var that = this, 23297 options = this.options; 23298 23299 function filteredUi( ui ) { 23300 return { 23301 position: ui.position, 23302 offset: ui.offset 23303 }; 23304 } 23305 23306 this.uiDialog.draggable( { 23307 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", 23308 handle: ".ui-dialog-titlebar", 23309 containment: "document", 23310 start: function( event, ui ) { 23311 that._addClass( $( this ), "ui-dialog-dragging" ); 23312 that._blockFrames(); 23313 that._trigger( "dragStart", event, filteredUi( ui ) ); 23314 }, 23315 drag: function( event, ui ) { 23316 that._trigger( "drag", event, filteredUi( ui ) ); 23317 }, 23318 stop: function( event, ui ) { 23319 var left = ui.offset.left - that.document.scrollLeft(), 23320 top = ui.offset.top - that.document.scrollTop(); 23321 23322 options.position = { 23323 my: "left top", 23324 at: "left" + ( left >= 0 ? "+" : "" ) + left + " " + 23325 "top" + ( top >= 0 ? "+" : "" ) + top, 23326 of: that.window 23327 }; 23328 that._removeClass( $( this ), "ui-dialog-dragging" ); 23329 that._unblockFrames(); 23330 that._trigger( "dragStop", event, filteredUi( ui ) ); 23331 } 23332 } ); 23333 }, 23334 23335 _makeResizable: function() { 23336 var that = this, 23337 options = this.options, 23338 handles = options.resizable, 23339 23340 // .ui-resizable has position: relative defined in the stylesheet 23341 // but dialogs have to use absolute or fixed positioning 23342 position = this.uiDialog.css( "position" ), 23343 resizeHandles = typeof handles === "string" ? 23344 handles : 23345 "n,e,s,w,se,sw,ne,nw"; 23346 23347 function filteredUi( ui ) { 23348 return { 23349 originalPosition: ui.originalPosition, 23350 originalSize: ui.originalSize, 23351 position: ui.position, 23352 size: ui.size 23353 }; 23354 } 23355 23356 this.uiDialog.resizable( { 23357 cancel: ".ui-dialog-content", 23358 containment: "document", 23359 alsoResize: this.element, 23360 maxWidth: options.maxWidth, 23361 maxHeight: options.maxHeight, 23362 minWidth: options.minWidth, 23363 minHeight: this._minHeight(), 23364 handles: resizeHandles, 23365 start: function( event, ui ) { 23366 that._addClass( $( this ), "ui-dialog-resizing" ); 23367 that._blockFrames(); 23368 that._trigger( "resizeStart", event, filteredUi( ui ) ); 23369 }, 23370 resize: function( event, ui ) { 23371 that._trigger( "resize", event, filteredUi( ui ) ); 23372 }, 23373 stop: function( event, ui ) { 23374 var offset = that.uiDialog.offset(), 23375 left = offset.left - that.document.scrollLeft(), 23376 top = offset.top - that.document.scrollTop(); 23377 23378 options.height = that.uiDialog.height(); 23379 options.width = that.uiDialog.width(); 23380 options.position = { 23381 my: "left top", 23382 at: "left" + ( left >= 0 ? "+" : "" ) + left + " " + 23383 "top" + ( top >= 0 ? "+" : "" ) + top, 23384 of: that.window 23385 }; 23386 that._removeClass( $( this ), "ui-dialog-resizing" ); 23387 that._unblockFrames(); 23388 that._trigger( "resizeStop", event, filteredUi( ui ) ); 23389 } 23390 } ) 23391 .css( "position", position ); 23392 }, 23393 23394 _trackFocus: function() { 23395 this._on( this.widget(), { 23396 focusin: function( event ) { 23397 this._makeFocusTarget(); 23398 this._focusedElement = $( event.target ); 23399 } 23400 } ); 23401 }, 23402 23403 _makeFocusTarget: function() { 23404 this._untrackInstance(); 23405 this._trackingInstances().unshift( this ); 23406 }, 23407 23408 _untrackInstance: function() { 23409 var instances = this._trackingInstances(), 23410 exists = $.inArray( this, instances ); 23411 if ( exists !== -1 ) { 23412 instances.splice( exists, 1 ); 23413 } 23414 }, 23415 23416 _trackingInstances: function() { 23417 var instances = this.document.data( "ui-dialog-instances" ); 23418 if ( !instances ) { 23419 instances = []; 23420 this.document.data( "ui-dialog-instances", instances ); 23421 } 23422 return instances; 23423 }, 23424 23425 _minHeight: function() { 23426 var options = this.options; 23427 23428 return options.height === "auto" ? 23429 options.minHeight : 23430 Math.min( options.minHeight, options.height ); 23431 }, 23432 23433 _position: function() { 23434 23435 // Need to show the dialog to get the actual offset in the position plugin 23436 var isVisible = this.uiDialog.is( ":visible" ); 23437 if ( !isVisible ) { 23438 this.uiDialog.show(); 23439 } 23440 this.uiDialog.position( this.options.position ); 23441 if ( !isVisible ) { 23442 this.uiDialog.hide(); 23443 } 23444 }, 23445 23446 _setOptions: function( options ) { 23447 var that = this, 23448 resize = false, 23449 resizableOptions = {}; 23450 23451 $.each( options, function( key, value ) { 23452 that._setOption( key, value ); 23453 23454 if ( key in that.sizeRelatedOptions ) { 23455 resize = true; 23456 } 23457 if ( key in that.resizableRelatedOptions ) { 23458 resizableOptions[ key ] = value; 23459 } 23460 } ); 23461 23462 if ( resize ) { 23463 this._size(); 23464 this._position(); 23465 } 23466 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { 23467 this.uiDialog.resizable( "option", resizableOptions ); 23468 } 23469 }, 23470 23471 _setOption: function( key, value ) { 23472 var isDraggable, isResizable, 23473 uiDialog = this.uiDialog; 23474 23475 if ( key === "disabled" ) { 23476 return; 23477 } 23478 23479 this._super( key, value ); 23480 23481 if ( key === "appendTo" ) { 23482 this.uiDialog.appendTo( this._appendTo() ); 23483 } 23484 23485 if ( key === "buttons" ) { 23486 this._createButtons(); 23487 } 23488 23489 if ( key === "closeText" ) { 23490 this.uiDialogTitlebarClose.button( { 23491 23492 // Ensure that we always pass a string 23493 label: $( "<a>" ).text( "" + this.options.closeText ).html() 23494 } ); 23495 } 23496 23497 if ( key === "draggable" ) { 23498 isDraggable = uiDialog.is( ":data(ui-draggable)" ); 23499 if ( isDraggable && !value ) { 23500 uiDialog.draggable( "destroy" ); 23501 } 23502 23503 if ( !isDraggable && value ) { 23504 this._makeDraggable(); 23505 } 23506 } 23507 23508 if ( key === "position" ) { 23509 this._position(); 23510 } 23511 23512 if ( key === "resizable" ) { 23513 23514 // currently resizable, becoming non-resizable 23515 isResizable = uiDialog.is( ":data(ui-resizable)" ); 23516 if ( isResizable && !value ) { 23517 uiDialog.resizable( "destroy" ); 23518 } 23519 23520 // Currently resizable, changing handles 23521 if ( isResizable && typeof value === "string" ) { 23522 uiDialog.resizable( "option", "handles", value ); 23523 } 23524 23525 // Currently non-resizable, becoming resizable 23526 if ( !isResizable && value !== false ) { 23527 this._makeResizable(); 23528 } 23529 } 23530 23531 if ( key === "title" ) { 23532 this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) ); 23533 } 23534 23535 if ( key === "modal" ) { 23536 uiDialog.attr( "aria-modal", value ? "true" : null ); 23537 } 23538 }, 23539 23540 _size: function() { 23541 23542 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 23543 // divs will both have width and height set, so we need to reset them 23544 var nonContentHeight, minContentHeight, maxContentHeight, 23545 options = this.options; 23546 23547 // Reset content sizing 23548 this.element.show().css( { 23549 width: "auto", 23550 minHeight: 0, 23551 maxHeight: "none", 23552 height: 0 23553 } ); 23554 23555 if ( options.minWidth > options.width ) { 23556 options.width = options.minWidth; 23557 } 23558 23559 // Reset wrapper sizing 23560 // determine the height of all the non-content elements 23561 nonContentHeight = this.uiDialog.css( { 23562 height: "auto", 23563 width: options.width 23564 } ) 23565 .outerHeight(); 23566 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); 23567 maxContentHeight = typeof options.maxHeight === "number" ? 23568 Math.max( 0, options.maxHeight - nonContentHeight ) : 23569 "none"; 23570 23571 if ( options.height === "auto" ) { 23572 this.element.css( { 23573 minHeight: minContentHeight, 23574 maxHeight: maxContentHeight, 23575 height: "auto" 23576 } ); 23577 } else { 23578 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); 23579 } 23580 23581 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { 23582 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); 23583 } 23584 }, 23585 23586 _blockFrames: function() { 23587 this.iframeBlocks = this.document.find( "iframe" ).map( function() { 23588 var iframe = $( this ); 23589 23590 return $( "<div>" ) 23591 .css( { 23592 position: "absolute", 23593 width: iframe.outerWidth(), 23594 height: iframe.outerHeight() 23595 } ) 23596 .appendTo( iframe.parent() ) 23597 .offset( iframe.offset() )[ 0 ]; 23598 } ); 23599 }, 23600 23601 _unblockFrames: function() { 23602 if ( this.iframeBlocks ) { 23603 this.iframeBlocks.remove(); 23604 delete this.iframeBlocks; 23605 } 23606 }, 23607 23608 _allowInteraction: function( event ) { 23609 if ( $( event.target ).closest( ".ui-dialog" ).length ) { 23610 return true; 23611 } 23612 23613 // TODO: Remove hack when datepicker implements 23614 // the .ui-front logic (#8989) 23615 return !!$( event.target ).closest( ".ui-datepicker" ).length; 23616 }, 23617 23618 _createOverlay: function() { 23619 if ( !this.options.modal ) { 23620 return; 23621 } 23622 23623 // We use a delay in case the overlay is created from an 23624 // event that we're going to be cancelling (#2804) 23625 var isOpening = true; 23626 this._delay( function() { 23627 isOpening = false; 23628 } ); 23629 23630 if ( !this.document.data( "ui-dialog-overlays" ) ) { 23631 23632 // Prevent use of anchors and inputs 23633 // This doesn't use `_on()` because it is a shared event handler 23634 // across all open modal dialogs. 23635 this.document.on( "focusin.ui-dialog", function( event ) { 23636 if ( isOpening ) { 23637 return; 23638 } 23639 23640 var instance = this._trackingInstances()[ 0 ]; 23641 if ( !instance._allowInteraction( event ) ) { 23642 event.preventDefault(); 23643 instance._focusTabbable(); 23644 } 23645 }.bind( this ) ); 23646 } 23647 23648 this.overlay = $( "<div>" ) 23649 .appendTo( this._appendTo() ); 23650 23651 this._addClass( this.overlay, null, "ui-widget-overlay ui-front" ); 23652 this._on( this.overlay, { 23653 mousedown: "_keepFocus" 23654 } ); 23655 this.document.data( "ui-dialog-overlays", 23656 ( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 ); 23657 }, 23658 23659 _destroyOverlay: function() { 23660 if ( !this.options.modal ) { 23661 return; 23662 } 23663 23664 if ( this.overlay ) { 23665 var overlays = this.document.data( "ui-dialog-overlays" ) - 1; 23666 23667 if ( !overlays ) { 23668 this.document.off( "focusin.ui-dialog" ); 23669 this.document.removeData( "ui-dialog-overlays" ); 23670 } else { 23671 this.document.data( "ui-dialog-overlays", overlays ); 23672 } 23673 23674 this.overlay.remove(); 23675 this.overlay = null; 23676 } 23677 } 23678} ); 23679 23680// DEPRECATED 23681// TODO: switch return back to widget declaration at top of file when this is removed 23682if ( $.uiBackCompat === true ) { 23683 23684 // Backcompat for dialogClass option 23685 $.widget( "ui.dialog", $.ui.dialog, { 23686 options: { 23687 dialogClass: "" 23688 }, 23689 _createWrapper: function() { 23690 this._super(); 23691 this.uiDialog.addClass( this.options.dialogClass ); 23692 }, 23693 _setOption: function( key, value ) { 23694 if ( key === "dialogClass" ) { 23695 this.uiDialog 23696 .removeClass( this.options.dialogClass ) 23697 .addClass( value ); 23698 } 23699 this._superApply( arguments ); 23700 } 23701 } ); 23702} 23703 23704var widgetsDialog = $.ui.dialog; 23705 23706 23707/*! 23708 * jQuery UI Droppable 1.14.1 23709 * https://jqueryui.com 23710 * 23711 * Copyright OpenJS Foundation and other contributors 23712 * Released under the MIT license. 23713 * https://jquery.org/license 23714 */ 23715 23716//>>label: Droppable 23717//>>group: Interactions 23718//>>description: Enables drop targets for draggable elements. 23719//>>docs: https://api.jqueryui.com/droppable/ 23720//>>demos: https://jqueryui.com/droppable/ 23721 23722 23723$.widget( "ui.droppable", { 23724 version: "1.14.1", 23725 widgetEventPrefix: "drop", 23726 options: { 23727 accept: "*", 23728 addClasses: true, 23729 greedy: false, 23730 scope: "default", 23731 tolerance: "intersect", 23732 23733 // Callbacks 23734 activate: null, 23735 deactivate: null, 23736 drop: null, 23737 out: null, 23738 over: null 23739 }, 23740 _create: function() { 23741 23742 var proportions, 23743 o = this.options, 23744 accept = o.accept; 23745 23746 this.isover = false; 23747 this.isout = true; 23748 23749 this.accept = typeof accept === "function" ? accept : function( d ) { 23750 return d.is( accept ); 23751 }; 23752 23753 this.proportions = function( /* valueToWrite */ ) { 23754 if ( arguments.length ) { 23755 23756 // Store the droppable's proportions 23757 proportions = arguments[ 0 ]; 23758 } else { 23759 23760 // Retrieve or derive the droppable's proportions 23761 return proportions ? 23762 proportions : 23763 proportions = { 23764 width: this.element[ 0 ].offsetWidth, 23765 height: this.element[ 0 ].offsetHeight 23766 }; 23767 } 23768 }; 23769 23770 this._addToManager( o.scope ); 23771 23772 if ( o.addClasses ) { 23773 this._addClass( "ui-droppable" ); 23774 } 23775 23776 }, 23777 23778 _addToManager: function( scope ) { 23779 23780 // Add the reference and positions to the manager 23781 $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || []; 23782 $.ui.ddmanager.droppables[ scope ].push( this ); 23783 }, 23784 23785 _splice: function( drop ) { 23786 var i = 0; 23787 for ( ; i < drop.length; i++ ) { 23788 if ( drop[ i ] === this ) { 23789 drop.splice( i, 1 ); 23790 } 23791 } 23792 }, 23793 23794 _destroy: function() { 23795 var drop = $.ui.ddmanager.droppables[ this.options.scope ]; 23796 23797 this._splice( drop ); 23798 }, 23799 23800 _setOption: function( key, value ) { 23801 23802 if ( key === "accept" ) { 23803 this.accept = typeof value === "function" ? value : function( d ) { 23804 return d.is( value ); 23805 }; 23806 } else if ( key === "scope" ) { 23807 var drop = $.ui.ddmanager.droppables[ this.options.scope ]; 23808 23809 this._splice( drop ); 23810 this._addToManager( value ); 23811 } 23812 23813 this._super( key, value ); 23814 }, 23815 23816 _activate: function( event ) { 23817 var draggable = $.ui.ddmanager.current; 23818 23819 this._addActiveClass(); 23820 if ( draggable ) { 23821 this._trigger( "activate", event, this.ui( draggable ) ); 23822 } 23823 }, 23824 23825 _deactivate: function( event ) { 23826 var draggable = $.ui.ddmanager.current; 23827 23828 this._removeActiveClass(); 23829 if ( draggable ) { 23830 this._trigger( "deactivate", event, this.ui( draggable ) ); 23831 } 23832 }, 23833 23834 _over: function( event ) { 23835 23836 var draggable = $.ui.ddmanager.current; 23837 23838 // Bail if draggable and droppable are same element 23839 if ( !draggable || ( draggable.currentItem || 23840 draggable.element )[ 0 ] === this.element[ 0 ] ) { 23841 return; 23842 } 23843 23844 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || 23845 draggable.element ) ) ) { 23846 this._addHoverClass(); 23847 this._trigger( "over", event, this.ui( draggable ) ); 23848 } 23849 23850 }, 23851 23852 _out: function( event ) { 23853 23854 var draggable = $.ui.ddmanager.current; 23855 23856 // Bail if draggable and droppable are same element 23857 if ( !draggable || ( draggable.currentItem || 23858 draggable.element )[ 0 ] === this.element[ 0 ] ) { 23859 return; 23860 } 23861 23862 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || 23863 draggable.element ) ) ) { 23864 this._removeHoverClass(); 23865 this._trigger( "out", event, this.ui( draggable ) ); 23866 } 23867 23868 }, 23869 23870 _drop: function( event, custom ) { 23871 23872 var draggable = custom || $.ui.ddmanager.current, 23873 childrenIntersection = false; 23874 23875 // Bail if draggable and droppable are same element 23876 if ( !draggable || ( draggable.currentItem || 23877 draggable.element )[ 0 ] === this.element[ 0 ] ) { 23878 return false; 23879 } 23880 23881 this.element 23882 .find( ":data(ui-droppable)" ) 23883 .not( ".ui-draggable-dragging" ) 23884 .each( function() { 23885 var inst = $( this ).droppable( "instance" ); 23886 if ( 23887 inst.options.greedy && 23888 !inst.options.disabled && 23889 inst.options.scope === draggable.options.scope && 23890 inst.accept.call( 23891 inst.element[ 0 ], ( draggable.currentItem || draggable.element ) 23892 ) && 23893 $.ui.intersect( 23894 draggable, 23895 $.extend( inst, { offset: inst.element.offset() } ), 23896 inst.options.tolerance, event 23897 ) 23898 ) { 23899 childrenIntersection = true; 23900 return false; 23901 } 23902 } ); 23903 if ( childrenIntersection ) { 23904 return false; 23905 } 23906 23907 if ( this.accept.call( this.element[ 0 ], 23908 ( draggable.currentItem || draggable.element ) ) ) { 23909 this._removeActiveClass(); 23910 this._removeHoverClass(); 23911 23912 this._trigger( "drop", event, this.ui( draggable ) ); 23913 return this.element; 23914 } 23915 23916 return false; 23917 23918 }, 23919 23920 ui: function( c ) { 23921 return { 23922 draggable: ( c.currentItem || c.element ), 23923 helper: c.helper, 23924 position: c.position, 23925 offset: c.positionAbs 23926 }; 23927 }, 23928 23929 // Extension points just to make backcompat sane and avoid duplicating logic 23930 // TODO: Remove in 1.14 along with call to it below 23931 _addHoverClass: function() { 23932 this._addClass( "ui-droppable-hover" ); 23933 }, 23934 23935 _removeHoverClass: function() { 23936 this._removeClass( "ui-droppable-hover" ); 23937 }, 23938 23939 _addActiveClass: function() { 23940 this._addClass( "ui-droppable-active" ); 23941 }, 23942 23943 _removeActiveClass: function() { 23944 this._removeClass( "ui-droppable-active" ); 23945 } 23946} ); 23947 23948$.ui.intersect = ( function() { 23949 function isOverAxis( x, reference, size ) { 23950 return ( x >= reference ) && ( x < ( reference + size ) ); 23951 } 23952 23953 return function( draggable, droppable, toleranceMode, event ) { 23954 23955 if ( !droppable.offset ) { 23956 return false; 23957 } 23958 23959 var x1 = ( draggable.positionAbs || 23960 draggable.position.absolute ).left + draggable.margins.left, 23961 y1 = ( draggable.positionAbs || 23962 draggable.position.absolute ).top + draggable.margins.top, 23963 x2 = x1 + draggable.helperProportions.width, 23964 y2 = y1 + draggable.helperProportions.height, 23965 l = droppable.offset.left, 23966 t = droppable.offset.top, 23967 r = l + droppable.proportions().width, 23968 b = t + droppable.proportions().height; 23969 23970 switch ( toleranceMode ) { 23971 case "fit": 23972 return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b ); 23973 case "intersect": 23974 return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half 23975 x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half 23976 t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half 23977 y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half 23978 case "pointer": 23979 return isOverAxis( event.pageY, t, droppable.proportions().height ) && 23980 isOverAxis( event.pageX, l, droppable.proportions().width ); 23981 case "touch": 23982 return ( 23983 ( y1 >= t && y1 <= b ) || // Top edge touching 23984 ( y2 >= t && y2 <= b ) || // Bottom edge touching 23985 ( y1 < t && y2 > b ) // Surrounded vertically 23986 ) && ( 23987 ( x1 >= l && x1 <= r ) || // Left edge touching 23988 ( x2 >= l && x2 <= r ) || // Right edge touching 23989 ( x1 < l && x2 > r ) // Surrounded horizontally 23990 ); 23991 default: 23992 return false; 23993 } 23994 }; 23995} )(); 23996 23997/* 23998 This manager tracks offsets of draggables and droppables 23999*/ 24000$.ui.ddmanager = { 24001 current: null, 24002 droppables: { "default": [] }, 24003 prepareOffsets: function( t, event ) { 24004 24005 var i, j, 24006 m = $.ui.ddmanager.droppables[ t.options.scope ] || [], 24007 type = event ? event.type : null, // workaround for #2317 24008 list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack(); 24009 24010 droppablesLoop: for ( i = 0; i < m.length; i++ ) { 24011 24012 // No disabled and non-accepted 24013 if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], 24014 ( t.currentItem || t.element ) ) ) ) { 24015 continue; 24016 } 24017 24018 // Filter out elements in the current dragged item 24019 for ( j = 0; j < list.length; j++ ) { 24020 if ( list[ j ] === m[ i ].element[ 0 ] ) { 24021 m[ i ].proportions().height = 0; 24022 continue droppablesLoop; 24023 } 24024 } 24025 24026 m[ i ].visible = m[ i ].element.css( "display" ) !== "none"; 24027 if ( !m[ i ].visible ) { 24028 continue; 24029 } 24030 24031 // Activate the droppable if used directly from draggables 24032 if ( type === "mousedown" ) { 24033 m[ i ]._activate.call( m[ i ], event ); 24034 } 24035 24036 m[ i ].offset = m[ i ].element.offset(); 24037 m[ i ].proportions( { 24038 width: m[ i ].element[ 0 ].offsetWidth, 24039 height: m[ i ].element[ 0 ].offsetHeight 24040 } ); 24041 24042 } 24043 24044 }, 24045 drop: function( draggable, event ) { 24046 24047 var dropped = false; 24048 24049 // Create a copy of the droppables in case the list changes during the drop (#9116) 24050 $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() { 24051 24052 if ( !this.options ) { 24053 return; 24054 } 24055 if ( !this.options.disabled && this.visible && 24056 $.ui.intersect( draggable, this, this.options.tolerance, event ) ) { 24057 dropped = this._drop.call( this, event ) || dropped; 24058 } 24059 24060 if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], 24061 ( draggable.currentItem || draggable.element ) ) ) { 24062 this.isout = true; 24063 this.isover = false; 24064 this._deactivate.call( this, event ); 24065 } 24066 24067 } ); 24068 return dropped; 24069 24070 }, 24071 dragStart: function( draggable, event ) { 24072 24073 // Listen for scrolling so that if the dragging causes scrolling the position of the 24074 // droppables can be recalculated (see #5003) 24075 draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() { 24076 if ( !draggable.options.refreshPositions ) { 24077 $.ui.ddmanager.prepareOffsets( draggable, event ); 24078 } 24079 } ); 24080 }, 24081 drag: function( draggable, event ) { 24082 24083 // If you have a highly dynamic page, you might try this option. It renders positions 24084 // every time you move the mouse. 24085 if ( draggable.options.refreshPositions ) { 24086 $.ui.ddmanager.prepareOffsets( draggable, event ); 24087 } 24088 24089 // Run through all droppables and check their positions based on specific tolerance options 24090 $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() { 24091 24092 if ( this.options.disabled || this.greedyChild || !this.visible ) { 24093 return; 24094 } 24095 24096 var parentInstance, scope, parent, 24097 intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ), 24098 c = !intersects && this.isover ? 24099 "isout" : 24100 ( intersects && !this.isover ? "isover" : null ); 24101 if ( !c ) { 24102 return; 24103 } 24104 24105 if ( this.options.greedy ) { 24106 24107 // find droppable parents with same scope 24108 scope = this.options.scope; 24109 parent = this.element.parents( ":data(ui-droppable)" ).filter( function() { 24110 return $( this ).droppable( "instance" ).options.scope === scope; 24111 } ); 24112 24113 if ( parent.length ) { 24114 parentInstance = $( parent[ 0 ] ).droppable( "instance" ); 24115 parentInstance.greedyChild = ( c === "isover" ); 24116 } 24117 } 24118 24119 // We just moved into a greedy child 24120 if ( parentInstance && c === "isover" ) { 24121 parentInstance.isover = false; 24122 parentInstance.isout = true; 24123 parentInstance._out.call( parentInstance, event ); 24124 } 24125 24126 this[ c ] = true; 24127 this[ c === "isout" ? "isover" : "isout" ] = false; 24128 this[ c === "isover" ? "_over" : "_out" ].call( this, event ); 24129 24130 // We just moved out of a greedy child 24131 if ( parentInstance && c === "isout" ) { 24132 parentInstance.isout = false; 24133 parentInstance.isover = true; 24134 parentInstance._over.call( parentInstance, event ); 24135 } 24136 } ); 24137 24138 }, 24139 dragStop: function( draggable, event ) { 24140 draggable.element.parentsUntil( "body" ).off( "scroll.droppable" ); 24141 24142 // Call prepareOffsets one final time since IE does not fire return scroll events when 24143 // overflow was caused by drag (see #5003) 24144 if ( !draggable.options.refreshPositions ) { 24145 $.ui.ddmanager.prepareOffsets( draggable, event ); 24146 } 24147 } 24148}; 24149 24150// DEPRECATED 24151// TODO: switch return back to widget declaration at top of file when this is removed 24152if ( $.uiBackCompat === true ) { 24153 24154 // Backcompat for activeClass and hoverClass options 24155 $.widget( "ui.droppable", $.ui.droppable, { 24156 options: { 24157 hoverClass: false, 24158 activeClass: false 24159 }, 24160 _addActiveClass: function() { 24161 this._super(); 24162 if ( this.options.activeClass ) { 24163 this.element.addClass( this.options.activeClass ); 24164 } 24165 }, 24166 _removeActiveClass: function() { 24167 this._super(); 24168 if ( this.options.activeClass ) { 24169 this.element.removeClass( this.options.activeClass ); 24170 } 24171 }, 24172 _addHoverClass: function() { 24173 this._super(); 24174 if ( this.options.hoverClass ) { 24175 this.element.addClass( this.options.hoverClass ); 24176 } 24177 }, 24178 _removeHoverClass: function() { 24179 this._super(); 24180 if ( this.options.hoverClass ) { 24181 this.element.removeClass( this.options.hoverClass ); 24182 } 24183 } 24184 } ); 24185} 24186 24187var widgetsDroppable = $.ui.droppable; 24188 24189 24190/*! 24191 * jQuery UI Progressbar 1.14.1 24192 * https://jqueryui.com 24193 * 24194 * Copyright OpenJS Foundation and other contributors 24195 * Released under the MIT license. 24196 * https://jquery.org/license 24197 */ 24198 24199//>>label: Progressbar 24200//>>group: Widgets 24201/* eslint-disable max-len */ 24202//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators. 24203/* eslint-enable max-len */ 24204//>>docs: https://api.jqueryui.com/progressbar/ 24205//>>demos: https://jqueryui.com/progressbar/ 24206//>>css.structure: ../../themes/base/core.css 24207//>>css.structure: ../../themes/base/progressbar.css 24208//>>css.theme: ../../themes/base/theme.css 24209 24210 24211var widgetsProgressbar = $.widget( "ui.progressbar", { 24212 version: "1.14.1", 24213 options: { 24214 classes: { 24215 "ui-progressbar": "ui-corner-all", 24216 "ui-progressbar-value": "ui-corner-left", 24217 "ui-progressbar-complete": "ui-corner-right" 24218 }, 24219 max: 100, 24220 value: 0, 24221 24222 change: null, 24223 complete: null 24224 }, 24225 24226 min: 0, 24227 24228 _create: function() { 24229 24230 // Constrain initial value 24231 this.oldValue = this.options.value = this._constrainedValue(); 24232 24233 this.element.attr( { 24234 24235 // Only set static values; aria-valuenow and aria-valuemax are 24236 // set inside _refreshValue() 24237 role: "progressbar", 24238 "aria-valuemin": this.min 24239 } ); 24240 this._addClass( "ui-progressbar", "ui-widget ui-widget-content" ); 24241 24242 this.valueDiv = $( "<div>" ).appendTo( this.element ); 24243 this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" ); 24244 this._refreshValue(); 24245 }, 24246 24247 _destroy: function() { 24248 this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" ); 24249 24250 this.valueDiv.remove(); 24251 }, 24252 24253 value: function( newValue ) { 24254 if ( newValue === undefined ) { 24255 return this.options.value; 24256 } 24257 24258 this.options.value = this._constrainedValue( newValue ); 24259 this._refreshValue(); 24260 }, 24261 24262 _constrainedValue: function( newValue ) { 24263 if ( newValue === undefined ) { 24264 newValue = this.options.value; 24265 } 24266 24267 this.indeterminate = newValue === false; 24268 24269 // Sanitize value 24270 if ( typeof newValue !== "number" ) { 24271 newValue = 0; 24272 } 24273 24274 return this.indeterminate ? false : 24275 Math.min( this.options.max, Math.max( this.min, newValue ) ); 24276 }, 24277 24278 _setOptions: function( options ) { 24279 24280 // Ensure "value" option is set after other values (like max) 24281 var value = options.value; 24282 delete options.value; 24283 24284 this._super( options ); 24285 24286 this.options.value = this._constrainedValue( value ); 24287 this._refreshValue(); 24288 }, 24289 24290 _setOption: function( key, value ) { 24291 if ( key === "max" ) { 24292 24293 // Don't allow a max less than min 24294 value = Math.max( this.min, value ); 24295 } 24296 this._super( key, value ); 24297 }, 24298 24299 _setOptionDisabled: function( value ) { 24300 this._super( value ); 24301 24302 this.element.attr( "aria-disabled", value ); 24303 this._toggleClass( null, "ui-state-disabled", !!value ); 24304 }, 24305 24306 _percentage: function() { 24307 return this.indeterminate ? 24308 100 : 24309 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); 24310 }, 24311 24312 _refreshValue: function() { 24313 var value = this.options.value, 24314 percentage = this._percentage(); 24315 24316 this.valueDiv 24317 .toggle( this.indeterminate || value > this.min ) 24318 .width( percentage.toFixed( 0 ) + "%" ); 24319 24320 this 24321 ._toggleClass( this.valueDiv, "ui-progressbar-complete", null, 24322 value === this.options.max ) 24323 ._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate ); 24324 24325 if ( this.indeterminate ) { 24326 this.element.removeAttr( "aria-valuenow" ); 24327 if ( !this.overlayDiv ) { 24328 this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv ); 24329 this._addClass( this.overlayDiv, "ui-progressbar-overlay" ); 24330 } 24331 } else { 24332 this.element.attr( { 24333 "aria-valuemax": this.options.max, 24334 "aria-valuenow": value 24335 } ); 24336 if ( this.overlayDiv ) { 24337 this.overlayDiv.remove(); 24338 this.overlayDiv = null; 24339 } 24340 } 24341 24342 if ( this.oldValue !== value ) { 24343 this.oldValue = value; 24344 this._trigger( "change" ); 24345 } 24346 if ( value === this.options.max ) { 24347 this._trigger( "complete" ); 24348 } 24349 } 24350} ); 24351 24352 24353/*! 24354 * jQuery UI Selectable 1.14.1 24355 * https://jqueryui.com 24356 * 24357 * Copyright OpenJS Foundation and other contributors 24358 * Released under the MIT license. 24359 * https://jquery.org/license 24360 */ 24361 24362//>>label: Selectable 24363//>>group: Interactions 24364//>>description: Allows groups of elements to be selected with the mouse. 24365//>>docs: https://api.jqueryui.com/selectable/ 24366//>>demos: https://jqueryui.com/selectable/ 24367//>>css.structure: ../../themes/base/selectable.css 24368 24369 24370var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, { 24371 version: "1.14.1", 24372 options: { 24373 appendTo: "body", 24374 autoRefresh: true, 24375 distance: 0, 24376 filter: "*", 24377 tolerance: "touch", 24378 24379 // Callbacks 24380 selected: null, 24381 selecting: null, 24382 start: null, 24383 stop: null, 24384 unselected: null, 24385 unselecting: null 24386 }, 24387 _create: function() { 24388 var that = this; 24389 24390 this._addClass( "ui-selectable" ); 24391 24392 this.dragged = false; 24393 24394 // Cache selectee children based on filter 24395 this.refresh = function() { 24396 that.elementPos = $( that.element[ 0 ] ).offset(); 24397 that.selectees = $( that.options.filter, that.element[ 0 ] ); 24398 that._addClass( that.selectees, "ui-selectee" ); 24399 that.selectees.each( function() { 24400 var $this = $( this ), 24401 selecteeOffset = $this.offset(), 24402 pos = { 24403 left: selecteeOffset.left - that.elementPos.left, 24404 top: selecteeOffset.top - that.elementPos.top 24405 }; 24406 $.data( this, "selectable-item", { 24407 element: this, 24408 $element: $this, 24409 left: pos.left, 24410 top: pos.top, 24411 right: pos.left + $this.outerWidth(), 24412 bottom: pos.top + $this.outerHeight(), 24413 startselected: false, 24414 selected: $this.hasClass( "ui-selected" ), 24415 selecting: $this.hasClass( "ui-selecting" ), 24416 unselecting: $this.hasClass( "ui-unselecting" ) 24417 } ); 24418 } ); 24419 }; 24420 this.refresh(); 24421 24422 this._mouseInit(); 24423 24424 this.helper = $( "<div>" ); 24425 this._addClass( this.helper, "ui-selectable-helper" ); 24426 }, 24427 24428 _destroy: function() { 24429 this.selectees.removeData( "selectable-item" ); 24430 this._mouseDestroy(); 24431 }, 24432 24433 _mouseStart: function( event ) { 24434 var that = this, 24435 options = this.options; 24436 24437 this.opos = [ event.pageX, event.pageY ]; 24438 this.elementPos = $( this.element[ 0 ] ).offset(); 24439 24440 if ( this.options.disabled ) { 24441 return; 24442 } 24443 24444 this.selectees = $( options.filter, this.element[ 0 ] ); 24445 24446 this._trigger( "start", event ); 24447 24448 $( options.appendTo ).append( this.helper ); 24449 24450 // position helper (lasso) 24451 this.helper.css( { 24452 "left": event.pageX, 24453 "top": event.pageY, 24454 "width": 0, 24455 "height": 0 24456 } ); 24457 24458 if ( options.autoRefresh ) { 24459 this.refresh(); 24460 } 24461 24462 this.selectees.filter( ".ui-selected" ).each( function() { 24463 var selectee = $.data( this, "selectable-item" ); 24464 selectee.startselected = true; 24465 if ( !event.metaKey && !event.ctrlKey ) { 24466 that._removeClass( selectee.$element, "ui-selected" ); 24467 selectee.selected = false; 24468 that._addClass( selectee.$element, "ui-unselecting" ); 24469 selectee.unselecting = true; 24470 24471 // selectable UNSELECTING callback 24472 that._trigger( "unselecting", event, { 24473 unselecting: selectee.element 24474 } ); 24475 } 24476 } ); 24477 24478 $( event.target ).parents().addBack().each( function() { 24479 var doSelect, 24480 selectee = $.data( this, "selectable-item" ); 24481 if ( selectee ) { 24482 doSelect = ( !event.metaKey && !event.ctrlKey ) || 24483 !selectee.$element.hasClass( "ui-selected" ); 24484 that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" ) 24485 ._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" ); 24486 selectee.unselecting = !doSelect; 24487 selectee.selecting = doSelect; 24488 selectee.selected = doSelect; 24489 24490 // selectable (UN)SELECTING callback 24491 if ( doSelect ) { 24492 that._trigger( "selecting", event, { 24493 selecting: selectee.element 24494 } ); 24495 } else { 24496 that._trigger( "unselecting", event, { 24497 unselecting: selectee.element 24498 } ); 24499 } 24500 return false; 24501 } 24502 } ); 24503 24504 }, 24505 24506 _mouseDrag: function( event ) { 24507 24508 this.dragged = true; 24509 24510 if ( this.options.disabled ) { 24511 return; 24512 } 24513 24514 var tmp, 24515 that = this, 24516 options = this.options, 24517 x1 = this.opos[ 0 ], 24518 y1 = this.opos[ 1 ], 24519 x2 = event.pageX, 24520 y2 = event.pageY; 24521 24522 if ( x1 > x2 ) { 24523 tmp = x2; x2 = x1; x1 = tmp; 24524 } 24525 if ( y1 > y2 ) { 24526 tmp = y2; y2 = y1; y1 = tmp; 24527 } 24528 this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } ); 24529 24530 this.selectees.each( function() { 24531 var selectee = $.data( this, "selectable-item" ), 24532 hit = false, 24533 offset = {}; 24534 24535 //prevent helper from being selected if appendTo: selectable 24536 if ( !selectee || selectee.element === that.element[ 0 ] ) { 24537 return; 24538 } 24539 24540 offset.left = selectee.left + that.elementPos.left; 24541 offset.right = selectee.right + that.elementPos.left; 24542 offset.top = selectee.top + that.elementPos.top; 24543 offset.bottom = selectee.bottom + that.elementPos.top; 24544 24545 if ( options.tolerance === "touch" ) { 24546 hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 || 24547 offset.bottom < y1 ) ); 24548 } else if ( options.tolerance === "fit" ) { 24549 hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 && 24550 offset.bottom < y2 ); 24551 } 24552 24553 if ( hit ) { 24554 24555 // SELECT 24556 if ( selectee.selected ) { 24557 that._removeClass( selectee.$element, "ui-selected" ); 24558 selectee.selected = false; 24559 } 24560 if ( selectee.unselecting ) { 24561 that._removeClass( selectee.$element, "ui-unselecting" ); 24562 selectee.unselecting = false; 24563 } 24564 if ( !selectee.selecting ) { 24565 that._addClass( selectee.$element, "ui-selecting" ); 24566 selectee.selecting = true; 24567 24568 // selectable SELECTING callback 24569 that._trigger( "selecting", event, { 24570 selecting: selectee.element 24571 } ); 24572 } 24573 } else { 24574 24575 // UNSELECT 24576 if ( selectee.selecting ) { 24577 if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) { 24578 that._removeClass( selectee.$element, "ui-selecting" ); 24579 selectee.selecting = false; 24580 that._addClass( selectee.$element, "ui-selected" ); 24581 selectee.selected = true; 24582 } else { 24583 that._removeClass( selectee.$element, "ui-selecting" ); 24584 selectee.selecting = false; 24585 if ( selectee.startselected ) { 24586 that._addClass( selectee.$element, "ui-unselecting" ); 24587 selectee.unselecting = true; 24588 } 24589 24590 // selectable UNSELECTING callback 24591 that._trigger( "unselecting", event, { 24592 unselecting: selectee.element 24593 } ); 24594 } 24595 } 24596 if ( selectee.selected ) { 24597 if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) { 24598 that._removeClass( selectee.$element, "ui-selected" ); 24599 selectee.selected = false; 24600 24601 that._addClass( selectee.$element, "ui-unselecting" ); 24602 selectee.unselecting = true; 24603 24604 // selectable UNSELECTING callback 24605 that._trigger( "unselecting", event, { 24606 unselecting: selectee.element 24607 } ); 24608 } 24609 } 24610 } 24611 } ); 24612 24613 return false; 24614 }, 24615 24616 _mouseStop: function( event ) { 24617 var that = this; 24618 24619 this.dragged = false; 24620 24621 $( ".ui-unselecting", this.element[ 0 ] ).each( function() { 24622 var selectee = $.data( this, "selectable-item" ); 24623 that._removeClass( selectee.$element, "ui-unselecting" ); 24624 selectee.unselecting = false; 24625 selectee.startselected = false; 24626 that._trigger( "unselected", event, { 24627 unselected: selectee.element 24628 } ); 24629 } ); 24630 $( ".ui-selecting", this.element[ 0 ] ).each( function() { 24631 var selectee = $.data( this, "selectable-item" ); 24632 that._removeClass( selectee.$element, "ui-selecting" ) 24633 ._addClass( selectee.$element, "ui-selected" ); 24634 selectee.selecting = false; 24635 selectee.selected = true; 24636 selectee.startselected = true; 24637 that._trigger( "selected", event, { 24638 selected: selectee.element 24639 } ); 24640 } ); 24641 this._trigger( "stop", event ); 24642 24643 this.helper.remove(); 24644 24645 return false; 24646 } 24647 24648} ); 24649 24650 24651/*! 24652 * jQuery UI Selectmenu 1.14.1 24653 * https://jqueryui.com 24654 * 24655 * Copyright OpenJS Foundation and other contributors 24656 * Released under the MIT license. 24657 * https://jquery.org/license 24658 */ 24659 24660//>>label: Selectmenu 24661//>>group: Widgets 24662/* eslint-disable max-len */ 24663//>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select. 24664/* eslint-enable max-len */ 24665//>>docs: https://api.jqueryui.com/selectmenu/ 24666//>>demos: https://jqueryui.com/selectmenu/ 24667//>>css.structure: ../../themes/base/core.css 24668//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css 24669//>>css.theme: ../../themes/base/theme.css 24670 24671 24672var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, { 24673 version: "1.14.1", 24674 defaultElement: "<select>", 24675 options: { 24676 appendTo: null, 24677 classes: { 24678 "ui-selectmenu-button-open": "ui-corner-top", 24679 "ui-selectmenu-button-closed": "ui-corner-all" 24680 }, 24681 disabled: null, 24682 icons: { 24683 button: "ui-icon-triangle-1-s" 24684 }, 24685 position: { 24686 my: "left top", 24687 at: "left bottom", 24688 collision: "none" 24689 }, 24690 width: false, 24691 24692 // Callbacks 24693 change: null, 24694 close: null, 24695 focus: null, 24696 open: null, 24697 select: null 24698 }, 24699 24700 _create: function() { 24701 var selectmenuId = this.element.uniqueId().attr( "id" ); 24702 this.ids = { 24703 element: selectmenuId, 24704 button: selectmenuId + "-button", 24705 menu: selectmenuId + "-menu" 24706 }; 24707 24708 this._drawButton(); 24709 this._drawMenu(); 24710 this._bindFormResetHandler(); 24711 24712 this._rendered = false; 24713 this.menuItems = $(); 24714 }, 24715 24716 _drawButton: function() { 24717 var icon, 24718 that = this, 24719 item = this._parseOption( 24720 this.element.find( "option:selected" ), 24721 this.element[ 0 ].selectedIndex 24722 ); 24723 24724 // Associate existing label with the new button 24725 this.labels = this.element.labels().attr( "for", this.ids.button ); 24726 this._on( this.labels, { 24727 click: function( event ) { 24728 this.button.trigger( "focus" ); 24729 event.preventDefault(); 24730 } 24731 } ); 24732 24733 // Hide original select element 24734 this.element.hide(); 24735 24736 // Create button 24737 this.button = $( "<span>", { 24738 tabindex: this.options.disabled ? -1 : 0, 24739 id: this.ids.button, 24740 role: "combobox", 24741 "aria-expanded": "false", 24742 "aria-autocomplete": "list", 24743 "aria-owns": this.ids.menu, 24744 "aria-haspopup": "true", 24745 title: this.element.attr( "title" ) 24746 } ) 24747 .insertAfter( this.element ); 24748 24749 this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed", 24750 "ui-button ui-widget" ); 24751 24752 icon = $( "<span>" ).appendTo( this.button ); 24753 this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button ); 24754 this.buttonItem = this._renderButtonItem( item ) 24755 .appendTo( this.button ); 24756 24757 if ( this.options.width !== false ) { 24758 this._resizeButton(); 24759 } 24760 24761 this._on( this.button, this._buttonEvents ); 24762 this.button.one( "focusin", function() { 24763 24764 // Delay rendering the menu items until the button receives focus. 24765 // The menu may have already been rendered via a programmatic open. 24766 if ( !that._rendered ) { 24767 that._refreshMenu(); 24768 } 24769 } ); 24770 }, 24771 24772 _drawMenu: function() { 24773 var that = this; 24774 24775 // Create menu 24776 this.menu = $( "<ul>", { 24777 "aria-hidden": "true", 24778 "aria-labelledby": this.ids.button, 24779 id: this.ids.menu 24780 } ); 24781 24782 // Wrap menu 24783 this.menuWrap = $( "<div>" ).append( this.menu ); 24784 this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" ); 24785 this.menuWrap.appendTo( this._appendTo() ); 24786 24787 // Initialize menu widget 24788 this.menuInstance = this.menu 24789 .menu( { 24790 classes: { 24791 "ui-menu": "ui-corner-bottom" 24792 }, 24793 role: "listbox", 24794 select: function( event, ui ) { 24795 event.preventDefault(); 24796 that._select( ui.item.data( "ui-selectmenu-item" ), event ); 24797 }, 24798 focus: function( event, ui ) { 24799 var item = ui.item.data( "ui-selectmenu-item" ); 24800 24801 // Prevent inital focus from firing and check if its a newly focused item 24802 if ( that.focusIndex != null && item.index !== that.focusIndex ) { 24803 that._trigger( "focus", event, { item: item } ); 24804 if ( !that.isOpen ) { 24805 that._select( item, event ); 24806 } 24807 } 24808 that.focusIndex = item.index; 24809 24810 that.button.attr( "aria-activedescendant", 24811 that.menuItems.eq( item.index ).attr( "id" ) ); 24812 } 24813 } ) 24814 .menu( "instance" ); 24815 24816 // Don't close the menu on mouseleave 24817 this.menuInstance._off( this.menu, "mouseleave" ); 24818 24819 // Cancel the menu's collapseAll on document click 24820 this.menuInstance._closeOnDocumentClick = function() { 24821 return false; 24822 }; 24823 24824 // Selects often contain empty items, but never contain dividers 24825 this.menuInstance._isDivider = function() { 24826 return false; 24827 }; 24828 }, 24829 24830 refresh: function() { 24831 this._refreshMenu(); 24832 this.buttonItem.replaceWith( 24833 this.buttonItem = this._renderButtonItem( 24834 24835 // Fall back to an empty object in case there are no options 24836 this._getSelectedItem().data( "ui-selectmenu-item" ) || {} 24837 ) 24838 ); 24839 if ( this.options.width === null ) { 24840 this._resizeButton(); 24841 } 24842 }, 24843 24844 _refreshMenu: function() { 24845 var item, 24846 options = this.element.find( "option" ); 24847 24848 this.menu.empty(); 24849 24850 this._parseOptions( options ); 24851 this._renderMenu( this.menu, this.items ); 24852 24853 this.menuInstance.refresh(); 24854 this.menuItems = this.menu.find( "li" ) 24855 .not( ".ui-selectmenu-optgroup" ) 24856 .find( ".ui-menu-item-wrapper" ); 24857 24858 this._rendered = true; 24859 24860 if ( !options.length ) { 24861 return; 24862 } 24863 24864 item = this._getSelectedItem(); 24865 24866 // Update the menu to have the correct item focused 24867 this.menuInstance.focus( null, item ); 24868 this._setAria( item.data( "ui-selectmenu-item" ) ); 24869 24870 // Set disabled state 24871 this._setOption( "disabled", this.element.prop( "disabled" ) ); 24872 }, 24873 24874 open: function( event ) { 24875 if ( this.options.disabled ) { 24876 return; 24877 } 24878 24879 // If this is the first time the menu is being opened, render the items 24880 if ( !this._rendered ) { 24881 this._refreshMenu(); 24882 } else { 24883 24884 // Menu clears focus on close, reset focus to selected item 24885 this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" ); 24886 this.menuInstance.focus( null, this._getSelectedItem() ); 24887 } 24888 24889 // If there are no options, don't open the menu 24890 if ( !this.menuItems.length ) { 24891 return; 24892 } 24893 24894 this.isOpen = true; 24895 this._toggleAttr(); 24896 this._resizeMenu(); 24897 this._position(); 24898 24899 this._on( this.document, this._documentClick ); 24900 24901 this._trigger( "open", event ); 24902 }, 24903 24904 _position: function() { 24905 this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) ); 24906 }, 24907 24908 close: function( event ) { 24909 if ( !this.isOpen ) { 24910 return; 24911 } 24912 24913 this.isOpen = false; 24914 this._toggleAttr(); 24915 24916 this.range = null; 24917 this._off( this.document ); 24918 24919 this._trigger( "close", event ); 24920 }, 24921 24922 widget: function() { 24923 return this.button; 24924 }, 24925 24926 menuWidget: function() { 24927 return this.menu; 24928 }, 24929 24930 _renderButtonItem: function( item ) { 24931 var buttonItem = $( "<span>" ); 24932 24933 this._setText( buttonItem, item.label ); 24934 this._addClass( buttonItem, "ui-selectmenu-text" ); 24935 24936 return buttonItem; 24937 }, 24938 24939 _renderMenu: function( ul, items ) { 24940 var that = this, 24941 currentOptgroup = ""; 24942 24943 $.each( items, function( index, item ) { 24944 var li; 24945 24946 if ( item.optgroup !== currentOptgroup ) { 24947 li = $( "<li>", { 24948 text: item.optgroup 24949 } ); 24950 that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" + 24951 ( item.element.parent( "optgroup" ).prop( "disabled" ) ? 24952 " ui-state-disabled" : 24953 "" ) ); 24954 24955 li.appendTo( ul ); 24956 24957 currentOptgroup = item.optgroup; 24958 } 24959 24960 that._renderItemData( ul, item ); 24961 } ); 24962 }, 24963 24964 _renderItemData: function( ul, item ) { 24965 return this._renderItem( ul, item ).data( "ui-selectmenu-item", item ); 24966 }, 24967 24968 _renderItem: function( ul, item ) { 24969 var li = $( "<li>" ), 24970 wrapper = $( "<div>", { 24971 title: item.element.attr( "title" ) 24972 } ); 24973 24974 if ( item.disabled ) { 24975 this._addClass( li, null, "ui-state-disabled" ); 24976 } 24977 24978 if ( item.hidden ) { 24979 li.prop( "hidden", true ); 24980 } else { 24981 this._setText( wrapper, item.label ); 24982 } 24983 24984 return li.append( wrapper ).appendTo( ul ); 24985 }, 24986 24987 _setText: function( element, value ) { 24988 if ( value ) { 24989 element.text( value ); 24990 } else { 24991 element.html( " " ); 24992 } 24993 }, 24994 24995 _move: function( direction, event ) { 24996 var item, next, 24997 filter = ".ui-menu-item"; 24998 24999 if ( this.isOpen ) { 25000 item = this.menuItems.eq( this.focusIndex ).parent( "li" ); 25001 } else { 25002 item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" ); 25003 filter += ":not(.ui-state-disabled)"; 25004 } 25005 25006 if ( direction === "first" || direction === "last" ) { 25007 next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 ); 25008 } else { 25009 next = item[ direction + "All" ]( filter ).eq( 0 ); 25010 } 25011 25012 if ( next.length ) { 25013 this.menuInstance.focus( event, next ); 25014 } 25015 }, 25016 25017 _getSelectedItem: function() { 25018 return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" ); 25019 }, 25020 25021 _toggle: function( event ) { 25022 this[ this.isOpen ? "close" : "open" ]( event ); 25023 }, 25024 25025 _setSelection: function() { 25026 var selection; 25027 25028 if ( !this.range ) { 25029 return; 25030 } 25031 25032 selection = window.getSelection(); 25033 selection.removeAllRanges(); 25034 selection.addRange( this.range ); 25035 }, 25036 25037 _documentClick: { 25038 mousedown: function( event ) { 25039 if ( !this.isOpen ) { 25040 return; 25041 } 25042 25043 if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + 25044 CSS.escape( this.ids.button ) ).length ) { 25045 this.close( event ); 25046 } 25047 } 25048 }, 25049 25050 _buttonEvents: { 25051 25052 // Prevent text selection from being reset when interacting with the selectmenu (#10144) 25053 mousedown: function() { 25054 var selection = window.getSelection(); 25055 if ( selection.rangeCount ) { 25056 this.range = selection.getRangeAt( 0 ); 25057 } 25058 }, 25059 25060 click: function( event ) { 25061 this._setSelection(); 25062 this._toggle( event ); 25063 }, 25064 25065 keydown: function( event ) { 25066 var preventDefault = true; 25067 switch ( event.keyCode ) { 25068 case $.ui.keyCode.TAB: 25069 case $.ui.keyCode.ESCAPE: 25070 this.close( event ); 25071 preventDefault = false; 25072 break; 25073 case $.ui.keyCode.ENTER: 25074 if ( this.isOpen ) { 25075 this._selectFocusedItem( event ); 25076 } 25077 break; 25078 case $.ui.keyCode.UP: 25079 if ( event.altKey ) { 25080 this._toggle( event ); 25081 } else { 25082 this._move( "prev", event ); 25083 } 25084 break; 25085 case $.ui.keyCode.DOWN: 25086 if ( event.altKey ) { 25087 this._toggle( event ); 25088 } else { 25089 this._move( "next", event ); 25090 } 25091 break; 25092 case $.ui.keyCode.SPACE: 25093 if ( this.isOpen ) { 25094 this._selectFocusedItem( event ); 25095 } else { 25096 this._toggle( event ); 25097 } 25098 break; 25099 case $.ui.keyCode.LEFT: 25100 this._move( "prev", event ); 25101 break; 25102 case $.ui.keyCode.RIGHT: 25103 this._move( "next", event ); 25104 break; 25105 case $.ui.keyCode.HOME: 25106 case $.ui.keyCode.PAGE_UP: 25107 this._move( "first", event ); 25108 break; 25109 case $.ui.keyCode.END: 25110 case $.ui.keyCode.PAGE_DOWN: 25111 this._move( "last", event ); 25112 break; 25113 default: 25114 this.menu.trigger( event ); 25115 preventDefault = false; 25116 } 25117 25118 if ( preventDefault ) { 25119 event.preventDefault(); 25120 } 25121 } 25122 }, 25123 25124 _selectFocusedItem: function( event ) { 25125 var item = this.menuItems.eq( this.focusIndex ).parent( "li" ); 25126 if ( !item.hasClass( "ui-state-disabled" ) ) { 25127 this._select( item.data( "ui-selectmenu-item" ), event ); 25128 } 25129 }, 25130 25131 _select: function( item, event ) { 25132 var oldIndex = this.element[ 0 ].selectedIndex; 25133 25134 // Change native select element 25135 this.element[ 0 ].selectedIndex = item.index; 25136 this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) ); 25137 this._setAria( item ); 25138 this._trigger( "select", event, { item: item } ); 25139 25140 if ( item.index !== oldIndex ) { 25141 this._trigger( "change", event, { item: item } ); 25142 } 25143 25144 this.close( event ); 25145 }, 25146 25147 _setAria: function( item ) { 25148 var id = this.menuItems.eq( item.index ).attr( "id" ); 25149 25150 this.button.attr( { 25151 "aria-labelledby": id, 25152 "aria-activedescendant": id 25153 } ); 25154 this.menu.attr( "aria-activedescendant", id ); 25155 }, 25156 25157 _setOption: function( key, value ) { 25158 if ( key === "icons" ) { 25159 var icon = this.button.find( "span.ui-icon" ); 25160 this._removeClass( icon, null, this.options.icons.button ) 25161 ._addClass( icon, null, value.button ); 25162 } 25163 25164 this._super( key, value ); 25165 25166 if ( key === "appendTo" ) { 25167 this.menuWrap.appendTo( this._appendTo() ); 25168 } 25169 25170 if ( key === "width" ) { 25171 this._resizeButton(); 25172 } 25173 }, 25174 25175 _setOptionDisabled: function( value ) { 25176 this._super( value ); 25177 25178 this.menuInstance.option( "disabled", value ); 25179 this.button.attr( "aria-disabled", value ); 25180 this._toggleClass( this.button, null, "ui-state-disabled", value ); 25181 25182 this.element.prop( "disabled", value ); 25183 if ( value ) { 25184 this.button.attr( "tabindex", -1 ); 25185 this.close(); 25186 } else { 25187 this.button.attr( "tabindex", 0 ); 25188 } 25189 }, 25190 25191 _appendTo: function() { 25192 var element = this.options.appendTo; 25193 25194 if ( element ) { 25195 element = element.jquery || element.nodeType ? 25196 $( element ) : 25197 this.document.find( element ).eq( 0 ); 25198 } 25199 25200 if ( !element || !element[ 0 ] ) { 25201 element = this.element.closest( ".ui-front, dialog" ); 25202 } 25203 25204 if ( !element.length ) { 25205 element = this.document[ 0 ].body; 25206 } 25207 25208 return element; 25209 }, 25210 25211 _toggleAttr: function() { 25212 this.button.attr( "aria-expanded", this.isOpen ); 25213 25214 // We can't use two _toggleClass() calls here, because we need to make sure 25215 // we always remove classes first and add them second, otherwise if both classes have the 25216 // same theme class, it will be removed after we add it. 25217 this._removeClass( this.button, "ui-selectmenu-button-" + 25218 ( this.isOpen ? "closed" : "open" ) ) 25219 ._addClass( this.button, "ui-selectmenu-button-" + 25220 ( this.isOpen ? "open" : "closed" ) ) 25221 ._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen ); 25222 25223 this.menu.attr( "aria-hidden", !this.isOpen ); 25224 }, 25225 25226 _resizeButton: function() { 25227 var width = this.options.width; 25228 25229 // For `width: false`, just remove inline style and stop 25230 if ( width === false ) { 25231 this.button.css( "width", "" ); 25232 return; 25233 } 25234 25235 // For `width: null`, match the width of the original element 25236 if ( width === null ) { 25237 width = this.element.show().outerWidth(); 25238 this.element.hide(); 25239 } 25240 25241 this.button.outerWidth( width ); 25242 }, 25243 25244 _resizeMenu: function() { 25245 this.menu.outerWidth( Math.max( 25246 this.button.outerWidth(), 25247 this.menu.width( "" ).outerWidth() 25248 ) ); 25249 }, 25250 25251 _getCreateOptions: function() { 25252 var options = this._super(); 25253 25254 options.disabled = this.element.prop( "disabled" ); 25255 25256 return options; 25257 }, 25258 25259 _parseOptions: function( options ) { 25260 var that = this, 25261 data = []; 25262 options.each( function( index, item ) { 25263 data.push( that._parseOption( $( item ), index ) ); 25264 } ); 25265 this.items = data; 25266 }, 25267 25268 _parseOption: function( option, index ) { 25269 var optgroup = option.parent( "optgroup" ); 25270 25271 return { 25272 element: option, 25273 index: index, 25274 value: option.val(), 25275 label: option.text(), 25276 hidden: optgroup.prop( "hidden" ) || option.prop( "hidden" ), 25277 optgroup: optgroup.attr( "label" ) || "", 25278 disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" ) 25279 }; 25280 }, 25281 25282 _destroy: function() { 25283 this._unbindFormResetHandler(); 25284 this.menuWrap.remove(); 25285 this.button.remove(); 25286 this.element.show(); 25287 this.element.removeUniqueId(); 25288 this.labels.attr( "for", this.ids.element ); 25289 } 25290} ] ); 25291 25292 25293/*! 25294 * jQuery UI Slider 1.14.1 25295 * https://jqueryui.com 25296 * 25297 * Copyright OpenJS Foundation and other contributors 25298 * Released under the MIT license. 25299 * https://jquery.org/license 25300 */ 25301 25302//>>label: Slider 25303//>>group: Widgets 25304//>>description: Displays a flexible slider with ranges and accessibility via keyboard. 25305//>>docs: https://api.jqueryui.com/slider/ 25306//>>demos: https://jqueryui.com/slider/ 25307//>>css.structure: ../../themes/base/core.css 25308//>>css.structure: ../../themes/base/slider.css 25309//>>css.theme: ../../themes/base/theme.css 25310 25311 25312var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, { 25313 version: "1.14.1", 25314 widgetEventPrefix: "slide", 25315 25316 options: { 25317 animate: false, 25318 classes: { 25319 "ui-slider": "ui-corner-all", 25320 "ui-slider-handle": "ui-corner-all", 25321 25322 // Note: ui-widget-header isn't the most fittingly semantic framework class for this 25323 // element, but worked best visually with a variety of themes 25324 "ui-slider-range": "ui-corner-all ui-widget-header" 25325 }, 25326 distance: 0, 25327 max: 100, 25328 min: 0, 25329 orientation: "horizontal", 25330 range: false, 25331 step: 1, 25332 value: 0, 25333 values: null, 25334 25335 // Callbacks 25336 change: null, 25337 slide: null, 25338 start: null, 25339 stop: null 25340 }, 25341 25342 // Number of pages in a slider 25343 // (how many times can you page up/down to go through the whole range) 25344 numPages: 5, 25345 25346 _create: function() { 25347 this._keySliding = false; 25348 this._mouseSliding = false; 25349 this._animateOff = true; 25350 this._handleIndex = null; 25351 this._detectOrientation(); 25352 this._mouseInit(); 25353 this._calculateNewMax(); 25354 25355 this._addClass( "ui-slider ui-slider-" + this.orientation, 25356 "ui-widget ui-widget-content" ); 25357 25358 this._refresh(); 25359 25360 this._animateOff = false; 25361 }, 25362 25363 _refresh: function() { 25364 this._createRange(); 25365 this._createHandles(); 25366 this._setupEvents(); 25367 this._refreshValue(); 25368 }, 25369 25370 _createHandles: function() { 25371 var i, handleCount, 25372 options = this.options, 25373 existingHandles = this.element.find( ".ui-slider-handle" ), 25374 handle = "<span tabindex='0'></span>", 25375 handles = []; 25376 25377 handleCount = ( options.values && options.values.length ) || 1; 25378 25379 if ( existingHandles.length > handleCount ) { 25380 existingHandles.slice( handleCount ).remove(); 25381 existingHandles = existingHandles.slice( 0, handleCount ); 25382 } 25383 25384 for ( i = existingHandles.length; i < handleCount; i++ ) { 25385 handles.push( handle ); 25386 } 25387 25388 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); 25389 25390 this._addClass( this.handles, "ui-slider-handle", "ui-state-default" ); 25391 25392 this.handle = this.handles.eq( 0 ); 25393 25394 this.handles.each( function( i ) { 25395 $( this ) 25396 .data( "ui-slider-handle-index", i ) 25397 .attr( "tabIndex", 0 ); 25398 } ); 25399 }, 25400 25401 _createRange: function() { 25402 var options = this.options; 25403 25404 if ( options.range ) { 25405 if ( options.range === true ) { 25406 if ( !options.values ) { 25407 options.values = [ this._valueMin(), this._valueMin() ]; 25408 } else if ( options.values.length && options.values.length !== 2 ) { 25409 options.values = [ options.values[ 0 ], options.values[ 0 ] ]; 25410 } else if ( Array.isArray( options.values ) ) { 25411 options.values = options.values.slice( 0 ); 25412 } 25413 } 25414 25415 if ( !this.range || !this.range.length ) { 25416 this.range = $( "<div>" ) 25417 .appendTo( this.element ); 25418 25419 this._addClass( this.range, "ui-slider-range" ); 25420 } else { 25421 this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" ); 25422 25423 // Handle range switching from true to min/max 25424 this.range.css( { 25425 "left": "", 25426 "bottom": "" 25427 } ); 25428 } 25429 if ( options.range === "min" || options.range === "max" ) { 25430 this._addClass( this.range, "ui-slider-range-" + options.range ); 25431 } 25432 } else { 25433 if ( this.range ) { 25434 this.range.remove(); 25435 } 25436 this.range = null; 25437 } 25438 }, 25439 25440 _setupEvents: function() { 25441 this._off( this.handles ); 25442 this._on( this.handles, this._handleEvents ); 25443 this._hoverable( this.handles ); 25444 this._focusable( this.handles ); 25445 }, 25446 25447 _destroy: function() { 25448 this.handles.remove(); 25449 if ( this.range ) { 25450 this.range.remove(); 25451 } 25452 25453 this._mouseDestroy(); 25454 }, 25455 25456 _mouseCapture: function( event ) { 25457 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, 25458 that = this, 25459 o = this.options; 25460 25461 if ( o.disabled ) { 25462 return false; 25463 } 25464 25465 this.elementSize = { 25466 width: this.element.outerWidth(), 25467 height: this.element.outerHeight() 25468 }; 25469 this.elementOffset = this.element.offset(); 25470 25471 position = { x: event.pageX, y: event.pageY }; 25472 normValue = this._normValueFromMouse( position ); 25473 distance = this._valueMax() - this._valueMin() + 1; 25474 this.handles.each( function( i ) { 25475 var thisDistance = Math.abs( normValue - that.values( i ) ); 25476 if ( ( distance > thisDistance ) || 25477 ( distance === thisDistance && 25478 ( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) { 25479 distance = thisDistance; 25480 closestHandle = $( this ); 25481 index = i; 25482 } 25483 } ); 25484 25485 allowed = this._start( event, index ); 25486 if ( allowed === false ) { 25487 return false; 25488 } 25489 this._mouseSliding = true; 25490 25491 this._handleIndex = index; 25492 25493 this._addClass( closestHandle, null, "ui-state-active" ); 25494 closestHandle.trigger( "focus" ); 25495 25496 offset = closestHandle.offset(); 25497 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); 25498 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 25499 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 25500 top: event.pageY - offset.top - 25501 ( closestHandle.height() / 2 ) - 25502 ( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) - 25503 ( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) + 25504 ( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 ) 25505 }; 25506 25507 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 25508 this._slide( event, index, normValue ); 25509 } 25510 this._animateOff = true; 25511 return true; 25512 }, 25513 25514 _mouseStart: function() { 25515 return true; 25516 }, 25517 25518 _mouseDrag: function( event ) { 25519 var position = { x: event.pageX, y: event.pageY }, 25520 normValue = this._normValueFromMouse( position ); 25521 25522 this._slide( event, this._handleIndex, normValue ); 25523 25524 return false; 25525 }, 25526 25527 _mouseStop: function( event ) { 25528 this._removeClass( this.handles, null, "ui-state-active" ); 25529 this._mouseSliding = false; 25530 25531 this._stop( event, this._handleIndex ); 25532 this._change( event, this._handleIndex ); 25533 25534 this._handleIndex = null; 25535 this._clickOffset = null; 25536 this._animateOff = false; 25537 25538 return false; 25539 }, 25540 25541 _detectOrientation: function() { 25542 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 25543 }, 25544 25545 _normValueFromMouse: function( position ) { 25546 var pixelTotal, 25547 pixelMouse, 25548 percentMouse, 25549 valueTotal, 25550 valueMouse; 25551 25552 if ( this.orientation === "horizontal" ) { 25553 pixelTotal = this.elementSize.width; 25554 pixelMouse = position.x - this.elementOffset.left - 25555 ( this._clickOffset ? this._clickOffset.left : 0 ); 25556 } else { 25557 pixelTotal = this.elementSize.height; 25558 pixelMouse = position.y - this.elementOffset.top - 25559 ( this._clickOffset ? this._clickOffset.top : 0 ); 25560 } 25561 25562 percentMouse = ( pixelMouse / pixelTotal ); 25563 if ( percentMouse > 1 ) { 25564 percentMouse = 1; 25565 } 25566 if ( percentMouse < 0 ) { 25567 percentMouse = 0; 25568 } 25569 if ( this.orientation === "vertical" ) { 25570 percentMouse = 1 - percentMouse; 25571 } 25572 25573 valueTotal = this._valueMax() - this._valueMin(); 25574 valueMouse = this._valueMin() + percentMouse * valueTotal; 25575 25576 return this._trimAlignValue( valueMouse ); 25577 }, 25578 25579 _uiHash: function( index, value, values ) { 25580 var uiHash = { 25581 handle: this.handles[ index ], 25582 handleIndex: index, 25583 value: value !== undefined ? value : this.value() 25584 }; 25585 25586 if ( this._hasMultipleValues() ) { 25587 uiHash.value = value !== undefined ? value : this.values( index ); 25588 uiHash.values = values || this.values(); 25589 } 25590 25591 return uiHash; 25592 }, 25593 25594 _hasMultipleValues: function() { 25595 return this.options.values && this.options.values.length; 25596 }, 25597 25598 _start: function( event, index ) { 25599 return this._trigger( "start", event, this._uiHash( index ) ); 25600 }, 25601 25602 _slide: function( event, index, newVal ) { 25603 var allowed, otherVal, 25604 currentValue = this.value(), 25605 newValues = this.values(); 25606 25607 if ( this._hasMultipleValues() ) { 25608 otherVal = this.values( index ? 0 : 1 ); 25609 currentValue = this.values( index ); 25610 25611 if ( this.options.values.length === 2 && this.options.range === true ) { 25612 newVal = index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal ); 25613 } 25614 25615 newValues[ index ] = newVal; 25616 } 25617 25618 if ( newVal === currentValue ) { 25619 return; 25620 } 25621 25622 allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) ); 25623 25624 // A slide can be canceled by returning false from the slide callback 25625 if ( allowed === false ) { 25626 return; 25627 } 25628 25629 if ( this._hasMultipleValues() ) { 25630 this.values( index, newVal ); 25631 } else { 25632 this.value( newVal ); 25633 } 25634 }, 25635 25636 _stop: function( event, index ) { 25637 this._trigger( "stop", event, this._uiHash( index ) ); 25638 }, 25639 25640 _change: function( event, index ) { 25641 if ( !this._keySliding && !this._mouseSliding ) { 25642 25643 //store the last changed value index for reference when handles overlap 25644 this._lastChangedValue = index; 25645 this._trigger( "change", event, this._uiHash( index ) ); 25646 } 25647 }, 25648 25649 value: function( newValue ) { 25650 if ( arguments.length ) { 25651 this.options.value = this._trimAlignValue( newValue ); 25652 this._refreshValue(); 25653 this._change( null, 0 ); 25654 return; 25655 } 25656 25657 return this._value(); 25658 }, 25659 25660 values: function( index, newValue ) { 25661 var vals, 25662 newValues, 25663 i; 25664 25665 if ( arguments.length > 1 ) { 25666 this.options.values[ index ] = this._trimAlignValue( newValue ); 25667 this._refreshValue(); 25668 this._change( null, index ); 25669 return; 25670 } 25671 25672 if ( arguments.length ) { 25673 if ( Array.isArray( arguments[ 0 ] ) ) { 25674 vals = this.options.values; 25675 newValues = arguments[ 0 ]; 25676 for ( i = 0; i < vals.length; i += 1 ) { 25677 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 25678 this._change( null, i ); 25679 } 25680 this._refreshValue(); 25681 } else { 25682 if ( this._hasMultipleValues() ) { 25683 return this._values( index ); 25684 } else { 25685 return this.value(); 25686 } 25687 } 25688 } else { 25689 return this._values(); 25690 } 25691 }, 25692 25693 _setOption: function( key, value ) { 25694 var i, 25695 valsLength = 0; 25696 25697 if ( key === "range" && this.options.range === true ) { 25698 if ( value === "min" ) { 25699 this.options.value = this._values( 0 ); 25700 this.options.values = null; 25701 } else if ( value === "max" ) { 25702 this.options.value = this._values( this.options.values.length - 1 ); 25703 this.options.values = null; 25704 } 25705 } 25706 25707 if ( Array.isArray( this.options.values ) ) { 25708 valsLength = this.options.values.length; 25709 } 25710 25711 this._super( key, value ); 25712 25713 switch ( key ) { 25714 case "orientation": 25715 this._detectOrientation(); 25716 this._removeClass( "ui-slider-horizontal ui-slider-vertical" ) 25717 ._addClass( "ui-slider-" + this.orientation ); 25718 this._refreshValue(); 25719 if ( this.options.range ) { 25720 this._refreshRange( value ); 25721 } 25722 25723 // Reset positioning from previous orientation 25724 this.handles.css( value === "horizontal" ? "bottom" : "left", "" ); 25725 break; 25726 case "value": 25727 this._animateOff = true; 25728 this._refreshValue(); 25729 this._change( null, 0 ); 25730 this._animateOff = false; 25731 break; 25732 case "values": 25733 this._animateOff = true; 25734 this._refreshValue(); 25735 25736 // Start from the last handle to prevent unreachable handles (#9046) 25737 for ( i = valsLength - 1; i >= 0; i-- ) { 25738 this._change( null, i ); 25739 } 25740 this._animateOff = false; 25741 break; 25742 case "step": 25743 case "min": 25744 case "max": 25745 this._animateOff = true; 25746 this._calculateNewMax(); 25747 this._refreshValue(); 25748 this._animateOff = false; 25749 break; 25750 case "range": 25751 this._animateOff = true; 25752 this._refresh(); 25753 this._animateOff = false; 25754 break; 25755 } 25756 }, 25757 25758 _setOptionDisabled: function( value ) { 25759 this._super( value ); 25760 25761 this._toggleClass( null, "ui-state-disabled", !!value ); 25762 }, 25763 25764 //internal value getter 25765 // _value() returns value trimmed by min and max, aligned by step 25766 _value: function() { 25767 var val = this.options.value; 25768 val = this._trimAlignValue( val ); 25769 25770 return val; 25771 }, 25772 25773 //internal values getter 25774 // _values() returns array of values trimmed by min and max, aligned by step 25775 // _values( index ) returns single value trimmed by min and max, aligned by step 25776 _values: function( index ) { 25777 var val, 25778 vals, 25779 i; 25780 25781 if ( arguments.length ) { 25782 val = this.options.values[ index ]; 25783 val = this._trimAlignValue( val ); 25784 25785 return val; 25786 } else if ( this._hasMultipleValues() ) { 25787 25788 // .slice() creates a copy of the array 25789 // this copy gets trimmed by min and max and then returned 25790 vals = this.options.values.slice(); 25791 for ( i = 0; i < vals.length; i += 1 ) { 25792 vals[ i ] = this._trimAlignValue( vals[ i ] ); 25793 } 25794 25795 return vals; 25796 } else { 25797 return []; 25798 } 25799 }, 25800 25801 // Returns the step-aligned value that val is closest to, between (inclusive) min and max 25802 _trimAlignValue: function( val ) { 25803 if ( val <= this._valueMin() ) { 25804 return this._valueMin(); 25805 } 25806 if ( val >= this._valueMax() ) { 25807 return this._valueMax(); 25808 } 25809 var step = ( this.options.step > 0 ) ? this.options.step : 1, 25810 valModStep = ( val - this._valueMin() ) % step, 25811 alignValue = val - valModStep; 25812 25813 if ( Math.abs( valModStep ) * 2 >= step ) { 25814 alignValue += ( valModStep > 0 ) ? step : ( -step ); 25815 } 25816 25817 // Since JavaScript has problems with large floats, round 25818 // the final value to 5 digits after the decimal point (see #4124) 25819 return parseFloat( alignValue.toFixed( 5 ) ); 25820 }, 25821 25822 _calculateNewMax: function() { 25823 var max = this.options.max, 25824 min = this._valueMin(), 25825 step = this.options.step, 25826 aboveMin = Math.round( ( max - min ) / step ) * step; 25827 max = aboveMin + min; 25828 if ( max > this.options.max ) { 25829 25830 //If max is not divisible by step, rounding off may increase its value 25831 max -= step; 25832 } 25833 this.max = parseFloat( max.toFixed( this._precision() ) ); 25834 }, 25835 25836 _precision: function() { 25837 var precision = this._precisionOf( this.options.step ); 25838 if ( this.options.min !== null ) { 25839 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 25840 } 25841 return precision; 25842 }, 25843 25844 _precisionOf: function( num ) { 25845 var str = num.toString(), 25846 decimal = str.indexOf( "." ); 25847 return decimal === -1 ? 0 : str.length - decimal - 1; 25848 }, 25849 25850 _valueMin: function() { 25851 return this.options.min; 25852 }, 25853 25854 _valueMax: function() { 25855 return this.max; 25856 }, 25857 25858 _refreshRange: function( orientation ) { 25859 if ( orientation === "vertical" ) { 25860 this.range.css( { "width": "", "left": "" } ); 25861 } 25862 if ( orientation === "horizontal" ) { 25863 this.range.css( { "height": "", "bottom": "" } ); 25864 } 25865 }, 25866 25867 _refreshValue: function() { 25868 var lastValPercent, valPercent, value, valueMin, valueMax, 25869 oRange = this.options.range, 25870 o = this.options, 25871 that = this, 25872 animate = ( !this._animateOff ) ? o.animate : false, 25873 _set = {}; 25874 25875 if ( this._hasMultipleValues() ) { 25876 this.handles.each( function( i ) { 25877 valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() - 25878 that._valueMin() ) * 100; 25879 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 25880 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 25881 if ( that.options.range === true ) { 25882 if ( that.orientation === "horizontal" ) { 25883 if ( i === 0 ) { 25884 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 25885 left: valPercent + "%" 25886 }, o.animate ); 25887 } 25888 if ( i === 1 ) { 25889 that.range[ animate ? "animate" : "css" ]( { 25890 width: ( valPercent - lastValPercent ) + "%" 25891 }, { 25892 queue: false, 25893 duration: o.animate 25894 } ); 25895 } 25896 } else { 25897 if ( i === 0 ) { 25898 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 25899 bottom: ( valPercent ) + "%" 25900 }, o.animate ); 25901 } 25902 if ( i === 1 ) { 25903 that.range[ animate ? "animate" : "css" ]( { 25904 height: ( valPercent - lastValPercent ) + "%" 25905 }, { 25906 queue: false, 25907 duration: o.animate 25908 } ); 25909 } 25910 } 25911 } 25912 lastValPercent = valPercent; 25913 } ); 25914 } else { 25915 value = this.value(); 25916 valueMin = this._valueMin(); 25917 valueMax = this._valueMax(); 25918 valPercent = ( valueMax !== valueMin ) ? 25919 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 25920 0; 25921 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 25922 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 25923 25924 if ( oRange === "min" && this.orientation === "horizontal" ) { 25925 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 25926 width: valPercent + "%" 25927 }, o.animate ); 25928 } 25929 if ( oRange === "max" && this.orientation === "horizontal" ) { 25930 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 25931 width: ( 100 - valPercent ) + "%" 25932 }, o.animate ); 25933 } 25934 if ( oRange === "min" && this.orientation === "vertical" ) { 25935 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 25936 height: valPercent + "%" 25937 }, o.animate ); 25938 } 25939 if ( oRange === "max" && this.orientation === "vertical" ) { 25940 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 25941 height: ( 100 - valPercent ) + "%" 25942 }, o.animate ); 25943 } 25944 } 25945 }, 25946 25947 _handleEvents: { 25948 keydown: function( event ) { 25949 var allowed, curVal, newVal, step, 25950 index = $( event.target ).data( "ui-slider-handle-index" ); 25951 25952 switch ( event.keyCode ) { 25953 case $.ui.keyCode.HOME: 25954 case $.ui.keyCode.END: 25955 case $.ui.keyCode.PAGE_UP: 25956 case $.ui.keyCode.PAGE_DOWN: 25957 case $.ui.keyCode.UP: 25958 case $.ui.keyCode.RIGHT: 25959 case $.ui.keyCode.DOWN: 25960 case $.ui.keyCode.LEFT: 25961 event.preventDefault(); 25962 if ( !this._keySliding ) { 25963 this._keySliding = true; 25964 this._addClass( $( event.target ), null, "ui-state-active" ); 25965 allowed = this._start( event, index ); 25966 if ( allowed === false ) { 25967 return; 25968 } 25969 } 25970 break; 25971 } 25972 25973 step = this.options.step; 25974 if ( this._hasMultipleValues() ) { 25975 curVal = newVal = this.values( index ); 25976 } else { 25977 curVal = newVal = this.value(); 25978 } 25979 25980 switch ( event.keyCode ) { 25981 case $.ui.keyCode.HOME: 25982 newVal = this._valueMin(); 25983 break; 25984 case $.ui.keyCode.END: 25985 newVal = this._valueMax(); 25986 break; 25987 case $.ui.keyCode.PAGE_UP: 25988 newVal = this._trimAlignValue( 25989 curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages ) 25990 ); 25991 break; 25992 case $.ui.keyCode.PAGE_DOWN: 25993 newVal = this._trimAlignValue( 25994 curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) ); 25995 break; 25996 case $.ui.keyCode.UP: 25997 case $.ui.keyCode.RIGHT: 25998 if ( curVal === this._valueMax() ) { 25999 return; 26000 } 26001 newVal = this._trimAlignValue( curVal + step ); 26002 break; 26003 case $.ui.keyCode.DOWN: 26004 case $.ui.keyCode.LEFT: 26005 if ( curVal === this._valueMin() ) { 26006 return; 26007 } 26008 newVal = this._trimAlignValue( curVal - step ); 26009 break; 26010 } 26011 26012 this._slide( event, index, newVal ); 26013 }, 26014 keyup: function( event ) { 26015 var index = $( event.target ).data( "ui-slider-handle-index" ); 26016 26017 if ( this._keySliding ) { 26018 this._keySliding = false; 26019 this._stop( event, index ); 26020 this._change( event, index ); 26021 this._removeClass( $( event.target ), null, "ui-state-active" ); 26022 } 26023 } 26024 } 26025} ); 26026 26027 26028/*! 26029 * jQuery UI Sortable 1.14.1 26030 * https://jqueryui.com 26031 * 26032 * Copyright OpenJS Foundation and other contributors 26033 * Released under the MIT license. 26034 * https://jquery.org/license 26035 */ 26036 26037//>>label: Sortable 26038//>>group: Interactions 26039//>>description: Enables items in a list to be sorted using the mouse. 26040//>>docs: https://api.jqueryui.com/sortable/ 26041//>>demos: https://jqueryui.com/sortable/ 26042//>>css.structure: ../../themes/base/sortable.css 26043 26044 26045var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, { 26046 version: "1.14.1", 26047 widgetEventPrefix: "sort", 26048 ready: false, 26049 options: { 26050 appendTo: "parent", 26051 axis: false, 26052 connectWith: false, 26053 containment: false, 26054 cursor: "auto", 26055 cursorAt: false, 26056 dropOnEmpty: true, 26057 forcePlaceholderSize: false, 26058 forceHelperSize: false, 26059 grid: false, 26060 handle: false, 26061 helper: "original", 26062 items: "> *", 26063 opacity: false, 26064 placeholder: false, 26065 revert: false, 26066 scroll: true, 26067 scrollSensitivity: 20, 26068 scrollSpeed: 20, 26069 scope: "default", 26070 tolerance: "intersect", 26071 zIndex: 1000, 26072 26073 // Callbacks 26074 activate: null, 26075 beforeStop: null, 26076 change: null, 26077 deactivate: null, 26078 out: null, 26079 over: null, 26080 receive: null, 26081 remove: null, 26082 sort: null, 26083 start: null, 26084 stop: null, 26085 update: null 26086 }, 26087 26088 _isOverAxis: function( x, reference, size ) { 26089 return ( x >= reference ) && ( x < ( reference + size ) ); 26090 }, 26091 26092 _isFloating: function( item ) { 26093 return ( /left|right/ ).test( item.css( "float" ) ) || 26094 ( /inline|table-cell/ ).test( item.css( "display" ) ); 26095 }, 26096 26097 _create: function() { 26098 this.containerCache = {}; 26099 this._addClass( "ui-sortable" ); 26100 26101 //Get the items 26102 this.refresh(); 26103 26104 //Let's determine the parent's offset 26105 this.offset = this.element.offset(); 26106 26107 //Initialize mouse events for interaction 26108 this._mouseInit(); 26109 26110 this._setHandleClassName(); 26111 26112 //We're ready to go 26113 this.ready = true; 26114 26115 }, 26116 26117 _setOption: function( key, value ) { 26118 this._super( key, value ); 26119 26120 if ( key === "handle" ) { 26121 this._setHandleClassName(); 26122 } 26123 }, 26124 26125 _setHandleClassName: function() { 26126 var that = this; 26127 this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" ); 26128 $.each( this.items, function() { 26129 that._addClass( 26130 this.instance.options.handle ? 26131 this.item.find( this.instance.options.handle ) : 26132 this.item, 26133 "ui-sortable-handle" 26134 ); 26135 } ); 26136 }, 26137 26138 _destroy: function() { 26139 this._mouseDestroy(); 26140 26141 for ( var i = this.items.length - 1; i >= 0; i-- ) { 26142 this.items[ i ].item.removeData( this.widgetName + "-item" ); 26143 } 26144 26145 return this; 26146 }, 26147 26148 _mouseCapture: function( event, overrideHandle ) { 26149 var currentItem = null, 26150 validHandle = false, 26151 that = this; 26152 26153 if ( this.reverting ) { 26154 return false; 26155 } 26156 26157 if ( this.options.disabled || this.options.type === "static" ) { 26158 return false; 26159 } 26160 26161 //We have to refresh the items data once first 26162 this._refreshItems( event ); 26163 26164 //Find out if the clicked node (or one of its parents) is a actual item in this.items 26165 $( event.target ).parents().each( function() { 26166 if ( $.data( this, that.widgetName + "-item" ) === that ) { 26167 currentItem = $( this ); 26168 return false; 26169 } 26170 } ); 26171 if ( $.data( event.target, that.widgetName + "-item" ) === that ) { 26172 currentItem = $( event.target ); 26173 } 26174 26175 if ( !currentItem ) { 26176 return false; 26177 } 26178 if ( this.options.handle && !overrideHandle ) { 26179 $( this.options.handle, currentItem ).find( "*" ).addBack().each( function() { 26180 if ( this === event.target ) { 26181 validHandle = true; 26182 } 26183 } ); 26184 if ( !validHandle ) { 26185 return false; 26186 } 26187 } 26188 26189 this.currentItem = currentItem; 26190 this._removeCurrentsFromItems(); 26191 return true; 26192 26193 }, 26194 26195 _mouseStart: function( event, overrideHandle, noActivation ) { 26196 26197 var i, body, 26198 o = this.options; 26199 26200 this.currentContainer = this; 26201 26202 //We only need to call refreshPositions, because the refreshItems call has been moved to 26203 // mouseCapture 26204 this.refreshPositions(); 26205 26206 //Prepare the dragged items parent 26207 this.appendTo = $( o.appendTo !== "parent" ? 26208 o.appendTo : 26209 this.currentItem.parent() ); 26210 26211 //Create and append the visible helper 26212 this.helper = this._createHelper( event ); 26213 26214 //Cache the helper size 26215 this._cacheHelperProportions(); 26216 26217 /* 26218 * - Position generation - 26219 * This block generates everything position related - it's the core of draggables. 26220 */ 26221 26222 //Cache the margins of the original element 26223 this._cacheMargins(); 26224 26225 //The element's absolute position on the page minus margins 26226 this.offset = this.currentItem.offset(); 26227 this.offset = { 26228 top: this.offset.top - this.margins.top, 26229 left: this.offset.left - this.margins.left 26230 }; 26231 26232 $.extend( this.offset, { 26233 click: { //Where the click happened, relative to the element 26234 left: event.pageX - this.offset.left, 26235 top: event.pageY - this.offset.top 26236 }, 26237 26238 // This is a relative to absolute position minus the actual position calculation - 26239 // only used for relative positioned helper 26240 relative: this._getRelativeOffset() 26241 } ); 26242 26243 // After we get the helper offset, but before we get the parent offset we can 26244 // change the helper's position to absolute 26245 // TODO: Still need to figure out a way to make relative sorting possible 26246 this.helper.css( "position", "absolute" ); 26247 this.cssPosition = this.helper.css( "position" ); 26248 26249 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 26250 if ( o.cursorAt ) { 26251 this._adjustOffsetFromHelper( o.cursorAt ); 26252 } 26253 26254 //Cache the former DOM position 26255 this.domPosition = { 26256 prev: this.currentItem.prev()[ 0 ], 26257 parent: this.currentItem.parent()[ 0 ] 26258 }; 26259 26260 // If the helper is not the original, hide the original so it's not playing any role during 26261 // the drag, won't cause anything bad this way 26262 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { 26263 this.currentItem.hide(); 26264 } 26265 26266 //Create the placeholder 26267 this._createPlaceholder(); 26268 26269 //Get the next scrolling parent 26270 this.scrollParent = this.placeholder.scrollParent(); 26271 26272 $.extend( this.offset, { 26273 parent: this._getParentOffset() 26274 } ); 26275 26276 //Set a containment if given in the options 26277 if ( o.containment ) { 26278 this._setContainment(); 26279 } 26280 26281 if ( o.cursor && o.cursor !== "auto" ) { // cursor option 26282 body = this.document.find( "body" ); 26283 26284 this._storedStylesheet = 26285 $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body ); 26286 } 26287 26288 // We need to make sure to grab the zIndex before setting the 26289 // opacity, because setting the opacity to anything lower than 1 26290 // causes the zIndex to change from "auto" to 0. 26291 if ( o.zIndex ) { // zIndex option 26292 if ( this.helper.css( "zIndex" ) ) { 26293 this._storedZIndex = this.helper.css( "zIndex" ); 26294 } 26295 this.helper.css( "zIndex", o.zIndex ); 26296 } 26297 26298 if ( o.opacity ) { // opacity option 26299 if ( this.helper.css( "opacity" ) ) { 26300 this._storedOpacity = this.helper.css( "opacity" ); 26301 } 26302 this.helper.css( "opacity", o.opacity ); 26303 } 26304 26305 //Prepare scrolling 26306 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 26307 this.scrollParent[ 0 ].tagName !== "HTML" ) { 26308 this.overflowOffset = this.scrollParent.offset(); 26309 } 26310 26311 //Call callbacks 26312 this._trigger( "start", event, this._uiHash() ); 26313 26314 //Recache the helper size 26315 if ( !this._preserveHelperProportions ) { 26316 this._cacheHelperProportions(); 26317 } 26318 26319 //Post "activate" events to possible containers 26320 if ( !noActivation ) { 26321 for ( i = this.containers.length - 1; i >= 0; i-- ) { 26322 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); 26323 } 26324 } 26325 26326 //Prepare possible droppables 26327 if ( $.ui.ddmanager ) { 26328 $.ui.ddmanager.current = this; 26329 } 26330 26331 if ( $.ui.ddmanager && !o.dropBehaviour ) { 26332 $.ui.ddmanager.prepareOffsets( this, event ); 26333 } 26334 26335 this.dragging = true; 26336 26337 this._addClass( this.helper, "ui-sortable-helper" ); 26338 26339 //Move the helper, if needed 26340 if ( !this.helper.parent().is( this.appendTo ) ) { 26341 this.helper.detach().appendTo( this.appendTo ); 26342 26343 //Update position 26344 this.offset.parent = this._getParentOffset(); 26345 } 26346 26347 //Generate the original position 26348 this.position = this.originalPosition = this._generatePosition( event ); 26349 this.originalPageX = event.pageX; 26350 this.originalPageY = event.pageY; 26351 this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" ); 26352 26353 this._mouseDrag( event ); 26354 26355 return true; 26356 26357 }, 26358 26359 _scroll: function( event ) { 26360 var o = this.options, 26361 scrolled = false; 26362 26363 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 26364 this.scrollParent[ 0 ].tagName !== "HTML" ) { 26365 26366 if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) - 26367 event.pageY < o.scrollSensitivity ) { 26368 this.scrollParent[ 0 ].scrollTop = 26369 scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed; 26370 } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) { 26371 this.scrollParent[ 0 ].scrollTop = 26372 scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed; 26373 } 26374 26375 if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) - 26376 event.pageX < o.scrollSensitivity ) { 26377 this.scrollParent[ 0 ].scrollLeft = scrolled = 26378 this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed; 26379 } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) { 26380 this.scrollParent[ 0 ].scrollLeft = scrolled = 26381 this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed; 26382 } 26383 26384 } else { 26385 26386 if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) { 26387 scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed ); 26388 } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) < 26389 o.scrollSensitivity ) { 26390 scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed ); 26391 } 26392 26393 if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) { 26394 scrolled = this.document.scrollLeft( 26395 this.document.scrollLeft() - o.scrollSpeed 26396 ); 26397 } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) < 26398 o.scrollSensitivity ) { 26399 scrolled = this.document.scrollLeft( 26400 this.document.scrollLeft() + o.scrollSpeed 26401 ); 26402 } 26403 26404 } 26405 26406 return scrolled; 26407 }, 26408 26409 _mouseDrag: function( event ) { 26410 var i, item, itemElement, intersection, 26411 o = this.options; 26412 26413 //Compute the helpers position 26414 this.position = this._generatePosition( event ); 26415 this.positionAbs = this._convertPositionTo( "absolute" ); 26416 26417 //Set the helper position 26418 if ( !this.options.axis || this.options.axis !== "y" ) { 26419 this.helper[ 0 ].style.left = this.position.left + "px"; 26420 } 26421 if ( !this.options.axis || this.options.axis !== "x" ) { 26422 this.helper[ 0 ].style.top = this.position.top + "px"; 26423 } 26424 26425 //Do scrolling 26426 if ( o.scroll ) { 26427 if ( this._scroll( event ) !== false ) { 26428 26429 //Update item positions used in position checks 26430 this._refreshItemPositions( true ); 26431 26432 if ( $.ui.ddmanager && !o.dropBehaviour ) { 26433 $.ui.ddmanager.prepareOffsets( this, event ); 26434 } 26435 } 26436 } 26437 26438 this.dragDirection = { 26439 vertical: this._getDragVerticalDirection(), 26440 horizontal: this._getDragHorizontalDirection() 26441 }; 26442 26443 //Rearrange 26444 for ( i = this.items.length - 1; i >= 0; i-- ) { 26445 26446 //Cache variables and intersection, continue if no intersection 26447 item = this.items[ i ]; 26448 itemElement = item.item[ 0 ]; 26449 intersection = this._intersectsWithPointer( item ); 26450 if ( !intersection ) { 26451 continue; 26452 } 26453 26454 // Only put the placeholder inside the current Container, skip all 26455 // items from other containers. This works because when moving 26456 // an item from one container to another the 26457 // currentContainer is switched before the placeholder is moved. 26458 // 26459 // Without this, moving items in "sub-sortables" can cause 26460 // the placeholder to jitter between the outer and inner container. 26461 if ( item.instance !== this.currentContainer ) { 26462 continue; 26463 } 26464 26465 // Cannot intersect with itself 26466 // no useless actions that have been done before 26467 // no action if the item moved is the parent of the item checked 26468 if ( itemElement !== this.currentItem[ 0 ] && 26469 this.placeholder[ intersection === 1 ? 26470 "next" : "prev" ]()[ 0 ] !== itemElement && 26471 !$.contains( this.placeholder[ 0 ], itemElement ) && 26472 ( this.options.type === "semi-dynamic" ? 26473 !$.contains( this.element[ 0 ], itemElement ) : 26474 true 26475 ) 26476 ) { 26477 26478 this.direction = intersection === 1 ? "down" : "up"; 26479 26480 if ( this.options.tolerance === "pointer" || 26481 this._intersectsWithSides( item ) ) { 26482 this._rearrange( event, item ); 26483 } else { 26484 break; 26485 } 26486 26487 this._trigger( "change", event, this._uiHash() ); 26488 break; 26489 } 26490 } 26491 26492 //Post events to containers 26493 this._contactContainers( event ); 26494 26495 //Interconnect with droppables 26496 if ( $.ui.ddmanager ) { 26497 $.ui.ddmanager.drag( this, event ); 26498 } 26499 26500 //Call callbacks 26501 this._trigger( "sort", event, this._uiHash() ); 26502 26503 this.lastPositionAbs = this.positionAbs; 26504 return false; 26505 26506 }, 26507 26508 _mouseStop: function( event, noPropagation ) { 26509 26510 if ( !event ) { 26511 return; 26512 } 26513 26514 //If we are using droppables, inform the manager about the drop 26515 if ( $.ui.ddmanager && !this.options.dropBehaviour ) { 26516 $.ui.ddmanager.drop( this, event ); 26517 } 26518 26519 if ( this.options.revert ) { 26520 var that = this, 26521 cur = this.placeholder.offset(), 26522 axis = this.options.axis, 26523 animation = {}; 26524 26525 if ( !axis || axis === "x" ) { 26526 animation.left = cur.left - this.offset.parent.left - this.margins.left + 26527 ( this.offsetParent[ 0 ] === this.document[ 0 ].body ? 26528 0 : 26529 this.offsetParent[ 0 ].scrollLeft 26530 ); 26531 } 26532 if ( !axis || axis === "y" ) { 26533 animation.top = cur.top - this.offset.parent.top - this.margins.top + 26534 ( this.offsetParent[ 0 ] === this.document[ 0 ].body ? 26535 0 : 26536 this.offsetParent[ 0 ].scrollTop 26537 ); 26538 } 26539 this.reverting = true; 26540 $( this.helper ).animate( 26541 animation, 26542 parseInt( this.options.revert, 10 ) || 500, 26543 function() { 26544 that._clear( event ); 26545 } 26546 ); 26547 } else { 26548 this._clear( event, noPropagation ); 26549 } 26550 26551 return false; 26552 26553 }, 26554 26555 cancel: function() { 26556 26557 if ( this.dragging ) { 26558 26559 this._mouseUp( new $.Event( "mouseup", { target: null } ) ); 26560 26561 if ( this.options.helper === "original" ) { 26562 this.currentItem.css( this._storedCSS ); 26563 this._removeClass( this.currentItem, "ui-sortable-helper" ); 26564 } else { 26565 this.currentItem.show(); 26566 } 26567 26568 //Post deactivating events to containers 26569 for ( var i = this.containers.length - 1; i >= 0; i-- ) { 26570 this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) ); 26571 if ( this.containers[ i ].containerCache.over ) { 26572 this.containers[ i ]._trigger( "out", null, this._uiHash( this ) ); 26573 this.containers[ i ].containerCache.over = 0; 26574 } 26575 } 26576 26577 } 26578 26579 if ( this.placeholder ) { 26580 26581 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, 26582 // it unbinds ALL events from the original node! 26583 if ( this.placeholder[ 0 ].parentNode ) { 26584 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] ); 26585 } 26586 if ( this.options.helper !== "original" && this.helper && 26587 this.helper[ 0 ].parentNode ) { 26588 this.helper.remove(); 26589 } 26590 26591 $.extend( this, { 26592 helper: null, 26593 dragging: false, 26594 reverting: false, 26595 _noFinalSort: null 26596 } ); 26597 26598 if ( this.domPosition.prev ) { 26599 $( this.domPosition.prev ).after( this.currentItem ); 26600 } else { 26601 $( this.domPosition.parent ).prepend( this.currentItem ); 26602 } 26603 } 26604 26605 return this; 26606 26607 }, 26608 26609 serialize: function( o ) { 26610 26611 var items = this._getItemsAsjQuery( o && o.connected ), 26612 str = []; 26613 o = o || {}; 26614 26615 $( items ).each( function() { 26616 var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" ) 26617 .match( o.expression || ( /(.+)[\-=_](.+)/ ) ); 26618 if ( res ) { 26619 str.push( 26620 ( o.key || res[ 1 ] + "[]" ) + 26621 "=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) ); 26622 } 26623 } ); 26624 26625 if ( !str.length && o.key ) { 26626 str.push( o.key + "=" ); 26627 } 26628 26629 return str.join( "&" ); 26630 26631 }, 26632 26633 toArray: function( o ) { 26634 26635 var items = this._getItemsAsjQuery( o && o.connected ), 26636 ret = []; 26637 26638 o = o || {}; 26639 26640 items.each( function() { 26641 ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" ); 26642 } ); 26643 return ret; 26644 26645 }, 26646 26647 /* Be careful with the following core functions */ 26648 _intersectsWith: function( item ) { 26649 26650 var x1 = this.positionAbs.left, 26651 x2 = x1 + this.helperProportions.width, 26652 y1 = this.positionAbs.top, 26653 y2 = y1 + this.helperProportions.height, 26654 l = item.left, 26655 r = l + item.width, 26656 t = item.top, 26657 b = t + item.height, 26658 dyClick = this.offset.click.top, 26659 dxClick = this.offset.click.left, 26660 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && 26661 ( y1 + dyClick ) < b ), 26662 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && 26663 ( x1 + dxClick ) < r ), 26664 isOverElement = isOverElementHeight && isOverElementWidth; 26665 26666 if ( this.options.tolerance === "pointer" || 26667 this.options.forcePointerForContainers || 26668 ( this.options.tolerance !== "pointer" && 26669 this.helperProportions[ this.floating ? "width" : "height" ] > 26670 item[ this.floating ? "width" : "height" ] ) 26671 ) { 26672 return isOverElement; 26673 } else { 26674 26675 return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half 26676 x2 - ( this.helperProportions.width / 2 ) < r && // Left Half 26677 t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half 26678 y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half 26679 26680 } 26681 }, 26682 26683 _intersectsWithPointer: function( item ) { 26684 var verticalDirection, horizontalDirection, 26685 isOverElementHeight = ( this.options.axis === "x" ) || 26686 this._isOverAxis( 26687 this.positionAbs.top + this.offset.click.top, item.top, item.height ), 26688 isOverElementWidth = ( this.options.axis === "y" ) || 26689 this._isOverAxis( 26690 this.positionAbs.left + this.offset.click.left, item.left, item.width ), 26691 isOverElement = isOverElementHeight && isOverElementWidth; 26692 26693 if ( !isOverElement ) { 26694 return false; 26695 } 26696 26697 verticalDirection = this.dragDirection.vertical; 26698 horizontalDirection = this.dragDirection.horizontal; 26699 26700 return this.floating ? 26701 ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) : 26702 ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) ); 26703 26704 }, 26705 26706 _intersectsWithSides: function( item ) { 26707 26708 var isOverBottomHalf = this._isOverAxis( this.positionAbs.top + 26709 this.offset.click.top, item.top + ( item.height / 2 ), item.height ), 26710 isOverRightHalf = this._isOverAxis( this.positionAbs.left + 26711 this.offset.click.left, item.left + ( item.width / 2 ), item.width ), 26712 verticalDirection = this.dragDirection.vertical, 26713 horizontalDirection = this.dragDirection.horizontal; 26714 26715 if ( this.floating && horizontalDirection ) { 26716 return ( ( horizontalDirection === "right" && isOverRightHalf ) || 26717 ( horizontalDirection === "left" && !isOverRightHalf ) ); 26718 } else { 26719 return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) || 26720 ( verticalDirection === "up" && !isOverBottomHalf ) ); 26721 } 26722 26723 }, 26724 26725 _getDragVerticalDirection: function() { 26726 var delta = this.positionAbs.top - this.lastPositionAbs.top; 26727 return delta !== 0 && ( delta > 0 ? "down" : "up" ); 26728 }, 26729 26730 _getDragHorizontalDirection: function() { 26731 var delta = this.positionAbs.left - this.lastPositionAbs.left; 26732 return delta !== 0 && ( delta > 0 ? "right" : "left" ); 26733 }, 26734 26735 refresh: function( event ) { 26736 this._refreshItems( event ); 26737 this._setHandleClassName(); 26738 this.refreshPositions(); 26739 return this; 26740 }, 26741 26742 _connectWith: function() { 26743 var options = this.options; 26744 return options.connectWith.constructor === String ? 26745 [ options.connectWith ] : 26746 options.connectWith; 26747 }, 26748 26749 _getItemsAsjQuery: function( connected ) { 26750 26751 var i, j, cur, inst, 26752 items = [], 26753 queries = [], 26754 connectWith = this._connectWith(); 26755 26756 if ( connectWith && connected ) { 26757 for ( i = connectWith.length - 1; i >= 0; i-- ) { 26758 cur = $( connectWith[ i ], this.document[ 0 ] ); 26759 for ( j = cur.length - 1; j >= 0; j-- ) { 26760 inst = $.data( cur[ j ], this.widgetFullName ); 26761 if ( inst && inst !== this && !inst.options.disabled ) { 26762 queries.push( [ typeof inst.options.items === "function" ? 26763 inst.options.items.call( inst.element ) : 26764 $( inst.options.items, inst.element ) 26765 .not( ".ui-sortable-helper" ) 26766 .not( ".ui-sortable-placeholder" ), inst ] ); 26767 } 26768 } 26769 } 26770 } 26771 26772 queries.push( [ typeof this.options.items === "function" ? 26773 this.options.items 26774 .call( this.element, null, { options: this.options, item: this.currentItem } ) : 26775 $( this.options.items, this.element ) 26776 .not( ".ui-sortable-helper" ) 26777 .not( ".ui-sortable-placeholder" ), this ] ); 26778 26779 function addItems() { 26780 items.push( this ); 26781 } 26782 for ( i = queries.length - 1; i >= 0; i-- ) { 26783 queries[ i ][ 0 ].each( addItems ); 26784 } 26785 26786 return $( items ); 26787 26788 }, 26789 26790 _removeCurrentsFromItems: function() { 26791 26792 var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" ); 26793 26794 this.items = $.grep( this.items, function( item ) { 26795 for ( var j = 0; j < list.length; j++ ) { 26796 if ( list[ j ] === item.item[ 0 ] ) { 26797 return false; 26798 } 26799 } 26800 return true; 26801 } ); 26802 26803 }, 26804 26805 _refreshItems: function( event ) { 26806 26807 this.items = []; 26808 this.containers = [ this ]; 26809 26810 var i, j, cur, inst, targetData, _queries, item, queriesLength, 26811 items = this.items, 26812 queries = [ [ typeof this.options.items === "function" ? 26813 this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) : 26814 $( this.options.items, this.element ), this ] ], 26815 connectWith = this._connectWith(); 26816 26817 //Shouldn't be run the first time through due to massive slow-down 26818 if ( connectWith && this.ready ) { 26819 for ( i = connectWith.length - 1; i >= 0; i-- ) { 26820 cur = $( connectWith[ i ], this.document[ 0 ] ); 26821 for ( j = cur.length - 1; j >= 0; j-- ) { 26822 inst = $.data( cur[ j ], this.widgetFullName ); 26823 if ( inst && inst !== this && !inst.options.disabled ) { 26824 queries.push( [ typeof inst.options.items === "function" ? 26825 inst.options.items 26826 .call( inst.element[ 0 ], event, { item: this.currentItem } ) : 26827 $( inst.options.items, inst.element ), inst ] ); 26828 this.containers.push( inst ); 26829 } 26830 } 26831 } 26832 } 26833 26834 for ( i = queries.length - 1; i >= 0; i-- ) { 26835 targetData = queries[ i ][ 1 ]; 26836 _queries = queries[ i ][ 0 ]; 26837 26838 for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) { 26839 item = $( _queries[ j ] ); 26840 26841 // Data for target checking (mouse manager) 26842 item.data( this.widgetName + "-item", targetData ); 26843 26844 items.push( { 26845 item: item, 26846 instance: targetData, 26847 width: 0, height: 0, 26848 left: 0, top: 0 26849 } ); 26850 } 26851 } 26852 26853 }, 26854 26855 _refreshItemPositions: function( fast ) { 26856 var i, item, t, p; 26857 26858 for ( i = this.items.length - 1; i >= 0; i-- ) { 26859 item = this.items[ i ]; 26860 26861 //We ignore calculating positions of all connected containers when we're not over them 26862 if ( this.currentContainer && item.instance !== this.currentContainer && 26863 item.item[ 0 ] !== this.currentItem[ 0 ] ) { 26864 continue; 26865 } 26866 26867 t = this.options.toleranceElement ? 26868 $( this.options.toleranceElement, item.item ) : 26869 item.item; 26870 26871 if ( !fast ) { 26872 item.width = t.outerWidth(); 26873 item.height = t.outerHeight(); 26874 } 26875 26876 p = t.offset(); 26877 item.left = p.left; 26878 item.top = p.top; 26879 } 26880 }, 26881 26882 refreshPositions: function( fast ) { 26883 26884 // Determine whether items are being displayed horizontally 26885 this.floating = this.items.length ? 26886 this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) : 26887 false; 26888 26889 // This has to be redone because due to the item being moved out/into the offsetParent, 26890 // the offsetParent's position will change 26891 if ( this.offsetParent && this.helper ) { 26892 this.offset.parent = this._getParentOffset(); 26893 } 26894 26895 this._refreshItemPositions( fast ); 26896 26897 var i, p; 26898 26899 if ( this.options.custom && this.options.custom.refreshContainers ) { 26900 this.options.custom.refreshContainers.call( this ); 26901 } else { 26902 for ( i = this.containers.length - 1; i >= 0; i-- ) { 26903 p = this.containers[ i ].element.offset(); 26904 this.containers[ i ].containerCache.left = p.left; 26905 this.containers[ i ].containerCache.top = p.top; 26906 this.containers[ i ].containerCache.width = 26907 this.containers[ i ].element.outerWidth(); 26908 this.containers[ i ].containerCache.height = 26909 this.containers[ i ].element.outerHeight(); 26910 } 26911 } 26912 26913 return this; 26914 }, 26915 26916 _createPlaceholder: function( that ) { 26917 that = that || this; 26918 var className, nodeName, 26919 o = that.options; 26920 26921 if ( !o.placeholder || o.placeholder.constructor === String ) { 26922 className = o.placeholder; 26923 nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(); 26924 o.placeholder = { 26925 element: function() { 26926 26927 var element = $( "<" + nodeName + ">", that.document[ 0 ] ); 26928 26929 that._addClass( element, "ui-sortable-placeholder", 26930 className || that.currentItem[ 0 ].className ) 26931 ._removeClass( element, "ui-sortable-helper" ); 26932 26933 if ( nodeName === "tbody" ) { 26934 that._createTrPlaceholder( 26935 that.currentItem.find( "tr" ).eq( 0 ), 26936 $( "<tr>", that.document[ 0 ] ).appendTo( element ) 26937 ); 26938 } else if ( nodeName === "tr" ) { 26939 that._createTrPlaceholder( that.currentItem, element ); 26940 } else if ( nodeName === "img" ) { 26941 element.attr( "src", that.currentItem.attr( "src" ) ); 26942 } 26943 26944 if ( !className ) { 26945 element.css( "visibility", "hidden" ); 26946 } 26947 26948 return element; 26949 }, 26950 update: function( container, p ) { 26951 26952 // 1. If a className is set as 'placeholder option, we don't force sizes - 26953 // the class is responsible for that 26954 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a 26955 // class name is specified 26956 if ( className && !o.forcePlaceholderSize ) { 26957 return; 26958 } 26959 26960 // If the element doesn't have a actual height or width by itself (without 26961 // styles coming from a stylesheet), it receives the inline height and width 26962 // from the dragged item. Or, if it's a tbody or tr, it's going to have a height 26963 // anyway since we're populating them with <td>s above, but they're unlikely to 26964 // be the correct height on their own if the row heights are dynamic, so we'll 26965 // always assign the height of the dragged item given forcePlaceholderSize 26966 // is true. 26967 if ( !p.height() || ( o.forcePlaceholderSize && 26968 ( nodeName === "tbody" || nodeName === "tr" ) ) ) { 26969 p.height( 26970 that.currentItem.innerHeight() - 26971 parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) - 26972 parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) ); 26973 } 26974 if ( !p.width() ) { 26975 p.width( 26976 that.currentItem.innerWidth() - 26977 parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) - 26978 parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) ); 26979 } 26980 } 26981 }; 26982 } 26983 26984 //Create the placeholder 26985 that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) ); 26986 26987 //Append it after the actual current item 26988 that.currentItem.after( that.placeholder ); 26989 26990 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 26991 o.placeholder.update( that, that.placeholder ); 26992 26993 }, 26994 26995 _createTrPlaceholder: function( sourceTr, targetTr ) { 26996 var that = this; 26997 26998 sourceTr.children().each( function() { 26999 $( "<td> </td>", that.document[ 0 ] ) 27000 .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) 27001 .appendTo( targetTr ); 27002 } ); 27003 }, 27004 27005 _contactContainers: function( event ) { 27006 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, 27007 floating, axis, 27008 innermostContainer = null, 27009 innermostIndex = null; 27010 27011 // Get innermost container that intersects with item 27012 for ( i = this.containers.length - 1; i >= 0; i-- ) { 27013 27014 // Never consider a container that's located within the item itself 27015 if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) { 27016 continue; 27017 } 27018 27019 if ( this._intersectsWith( this.containers[ i ].containerCache ) ) { 27020 27021 // If we've already found a container and it's more "inner" than this, then continue 27022 if ( innermostContainer && 27023 $.contains( 27024 this.containers[ i ].element[ 0 ], 27025 innermostContainer.element[ 0 ] ) ) { 27026 continue; 27027 } 27028 27029 innermostContainer = this.containers[ i ]; 27030 innermostIndex = i; 27031 27032 } else { 27033 27034 // container doesn't intersect. trigger "out" event if necessary 27035 if ( this.containers[ i ].containerCache.over ) { 27036 this.containers[ i ]._trigger( "out", event, this._uiHash( this ) ); 27037 this.containers[ i ].containerCache.over = 0; 27038 } 27039 } 27040 27041 } 27042 27043 // If no intersecting containers found, return 27044 if ( !innermostContainer ) { 27045 return; 27046 } 27047 27048 // Move the item into the container if it's not there already 27049 if ( this.containers.length === 1 ) { 27050 if ( !this.containers[ innermostIndex ].containerCache.over ) { 27051 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); 27052 this.containers[ innermostIndex ].containerCache.over = 1; 27053 } 27054 } else { 27055 27056 // When entering a new container, we will find the item with the least distance and 27057 // append our item near it 27058 dist = 10000; 27059 itemWithLeastDistance = null; 27060 floating = innermostContainer.floating || this._isFloating( this.currentItem ); 27061 posProperty = floating ? "left" : "top"; 27062 sizeProperty = floating ? "width" : "height"; 27063 axis = floating ? "pageX" : "pageY"; 27064 27065 for ( j = this.items.length - 1; j >= 0; j-- ) { 27066 if ( !$.contains( 27067 this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] ) 27068 ) { 27069 continue; 27070 } 27071 if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) { 27072 continue; 27073 } 27074 27075 cur = this.items[ j ].item.offset()[ posProperty ]; 27076 nearBottom = false; 27077 if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) { 27078 nearBottom = true; 27079 } 27080 27081 if ( Math.abs( event[ axis ] - cur ) < dist ) { 27082 dist = Math.abs( event[ axis ] - cur ); 27083 itemWithLeastDistance = this.items[ j ]; 27084 this.direction = nearBottom ? "up" : "down"; 27085 } 27086 } 27087 27088 //Check if dropOnEmpty is enabled 27089 if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) { 27090 return; 27091 } 27092 27093 if ( this.currentContainer === this.containers[ innermostIndex ] ) { 27094 if ( !this.currentContainer.containerCache.over ) { 27095 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() ); 27096 this.currentContainer.containerCache.over = 1; 27097 } 27098 return; 27099 } 27100 27101 if ( itemWithLeastDistance ) { 27102 this._rearrange( event, itemWithLeastDistance, null, true ); 27103 } else { 27104 this._rearrange( event, null, this.containers[ innermostIndex ].element, true ); 27105 } 27106 this._trigger( "change", event, this._uiHash() ); 27107 this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) ); 27108 this.currentContainer = this.containers[ innermostIndex ]; 27109 27110 //Update the placeholder 27111 this.options.placeholder.update( this.currentContainer, this.placeholder ); 27112 27113 //Update scrollParent 27114 this.scrollParent = this.placeholder.scrollParent(); 27115 27116 //Update overflowOffset 27117 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 27118 this.scrollParent[ 0 ].tagName !== "HTML" ) { 27119 this.overflowOffset = this.scrollParent.offset(); 27120 } 27121 27122 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); 27123 this.containers[ innermostIndex ].containerCache.over = 1; 27124 } 27125 27126 }, 27127 27128 _createHelper: function( event ) { 27129 27130 var o = this.options, 27131 helper = typeof o.helper === "function" ? 27132 $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) : 27133 ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem ); 27134 27135 //Add the helper to the DOM if that didn't happen already 27136 if ( !helper.parents( "body" ).length ) { 27137 this.appendTo[ 0 ].appendChild( helper[ 0 ] ); 27138 } 27139 27140 if ( helper[ 0 ] === this.currentItem[ 0 ] ) { 27141 this._storedCSS = { 27142 width: this.currentItem[ 0 ].style.width, 27143 height: this.currentItem[ 0 ].style.height, 27144 position: this.currentItem.css( "position" ), 27145 top: this.currentItem.css( "top" ), 27146 left: this.currentItem.css( "left" ) 27147 }; 27148 } 27149 27150 if ( !helper[ 0 ].style.width || o.forceHelperSize ) { 27151 helper.width( this.currentItem.width() ); 27152 } 27153 if ( !helper[ 0 ].style.height || o.forceHelperSize ) { 27154 helper.height( this.currentItem.height() ); 27155 } 27156 27157 return helper; 27158 27159 }, 27160 27161 _adjustOffsetFromHelper: function( obj ) { 27162 if ( typeof obj === "string" ) { 27163 obj = obj.split( " " ); 27164 } 27165 if ( Array.isArray( obj ) ) { 27166 obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 }; 27167 } 27168 if ( "left" in obj ) { 27169 this.offset.click.left = obj.left + this.margins.left; 27170 } 27171 if ( "right" in obj ) { 27172 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 27173 } 27174 if ( "top" in obj ) { 27175 this.offset.click.top = obj.top + this.margins.top; 27176 } 27177 if ( "bottom" in obj ) { 27178 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 27179 } 27180 }, 27181 27182 _getParentOffset: function() { 27183 27184 //Get the offsetParent and cache its position 27185 this.offsetParent = this.helper.offsetParent(); 27186 var po = this.offsetParent.offset(); 27187 27188 // This is a special case where we need to modify a offset calculated on start, since the 27189 // following happened: 27190 // 1. The position of the helper is absolute, so it's position is calculated based on the 27191 // next positioned parent 27192 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't 27193 // the document, which means that the scroll is included in the initial calculation of the 27194 // offset of the parent, and never recalculated upon drag 27195 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] && 27196 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { 27197 po.left += this.scrollParent.scrollLeft(); 27198 po.top += this.scrollParent.scrollTop(); 27199 } 27200 27201 // This needs to be actually done for all browsers, since pageX/pageY includes 27202 // this information. 27203 if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ) { 27204 po = { top: 0, left: 0 }; 27205 } 27206 27207 return { 27208 top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ), 27209 left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 ) 27210 }; 27211 27212 }, 27213 27214 _getRelativeOffset: function() { 27215 27216 if ( this.cssPosition === "relative" ) { 27217 var p = this.currentItem.position(); 27218 return { 27219 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) + 27220 this.scrollParent.scrollTop(), 27221 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) + 27222 this.scrollParent.scrollLeft() 27223 }; 27224 } else { 27225 return { top: 0, left: 0 }; 27226 } 27227 27228 }, 27229 27230 _cacheMargins: function() { 27231 this.margins = { 27232 left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ), 27233 top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 ) 27234 }; 27235 }, 27236 27237 _cacheHelperProportions: function() { 27238 this.helperProportions = { 27239 width: this.helper.outerWidth(), 27240 height: this.helper.outerHeight() 27241 }; 27242 }, 27243 27244 _setContainment: function() { 27245 27246 var ce, co, over, 27247 o = this.options; 27248 if ( o.containment === "parent" ) { 27249 o.containment = this.helper[ 0 ].parentNode; 27250 } 27251 if ( o.containment === "document" || o.containment === "window" ) { 27252 this.containment = [ 27253 0 - this.offset.relative.left - this.offset.parent.left, 27254 0 - this.offset.relative.top - this.offset.parent.top, 27255 o.containment === "document" ? 27256 this.document.width() : 27257 this.window.width() - this.helperProportions.width - this.margins.left, 27258 ( o.containment === "document" ? 27259 ( this.document.height() || document.body.parentNode.scrollHeight ) : 27260 this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight 27261 ) - this.helperProportions.height - this.margins.top 27262 ]; 27263 } 27264 27265 if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) { 27266 ce = $( o.containment )[ 0 ]; 27267 co = $( o.containment ).offset(); 27268 over = ( $( ce ).css( "overflow" ) !== "hidden" ); 27269 27270 this.containment = [ 27271 co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) + 27272 ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left, 27273 co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) + 27274 ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top, 27275 co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - 27276 ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) - 27277 ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) - 27278 this.helperProportions.width - this.margins.left, 27279 co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - 27280 ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) - 27281 ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) - 27282 this.helperProportions.height - this.margins.top 27283 ]; 27284 } 27285 27286 }, 27287 27288 _convertPositionTo: function( d, pos ) { 27289 27290 if ( !pos ) { 27291 pos = this.position; 27292 } 27293 var mod = d === "absolute" ? 1 : -1, 27294 scroll = this.cssPosition === "absolute" && 27295 !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 27296 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? 27297 this.offsetParent : 27298 this.scrollParent, 27299 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); 27300 27301 return { 27302 top: ( 27303 27304 // The absolute mouse position 27305 pos.top + 27306 27307 // Only for relative positioned nodes: Relative offset from element to offset parent 27308 this.offset.relative.top * mod + 27309 27310 // The offsetParent's offset without borders (offset + border) 27311 this.offset.parent.top * mod - 27312 ( ( this.cssPosition === "fixed" ? 27313 -this.scrollParent.scrollTop() : 27314 ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod ) 27315 ), 27316 left: ( 27317 27318 // The absolute mouse position 27319 pos.left + 27320 27321 // Only for relative positioned nodes: Relative offset from element to offset parent 27322 this.offset.relative.left * mod + 27323 27324 // The offsetParent's offset without borders (offset + border) 27325 this.offset.parent.left * mod - 27326 ( ( this.cssPosition === "fixed" ? 27327 -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : 27328 scroll.scrollLeft() ) * mod ) 27329 ) 27330 }; 27331 27332 }, 27333 27334 _generatePosition: function( event ) { 27335 27336 var top, left, 27337 o = this.options, 27338 pageX = event.pageX, 27339 pageY = event.pageY, 27340 scroll = this.cssPosition === "absolute" && 27341 !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 27342 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? 27343 this.offsetParent : 27344 this.scrollParent, 27345 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); 27346 27347 // This is another very weird special case that only happens for relative elements: 27348 // 1. If the css position is relative 27349 // 2. and the scroll parent is the document or similar to the offset parent 27350 // we have to refresh the relative offset during the scroll so there are no jumps 27351 if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 27352 this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) { 27353 this.offset.relative = this._getRelativeOffset(); 27354 } 27355 27356 /* 27357 * - Position constraining - 27358 * Constrain the position to a mix of grid, containment. 27359 */ 27360 27361 if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options 27362 27363 if ( this.containment ) { 27364 if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) { 27365 pageX = this.containment[ 0 ] + this.offset.click.left; 27366 } 27367 if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) { 27368 pageY = this.containment[ 1 ] + this.offset.click.top; 27369 } 27370 if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) { 27371 pageX = this.containment[ 2 ] + this.offset.click.left; 27372 } 27373 if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) { 27374 pageY = this.containment[ 3 ] + this.offset.click.top; 27375 } 27376 } 27377 27378 if ( o.grid ) { 27379 top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) / 27380 o.grid[ 1 ] ) * o.grid[ 1 ]; 27381 pageY = this.containment ? 27382 ( ( top - this.offset.click.top >= this.containment[ 1 ] && 27383 top - this.offset.click.top <= this.containment[ 3 ] ) ? 27384 top : 27385 ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ? 27386 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : 27387 top; 27388 27389 left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) / 27390 o.grid[ 0 ] ) * o.grid[ 0 ]; 27391 pageX = this.containment ? 27392 ( ( left - this.offset.click.left >= this.containment[ 0 ] && 27393 left - this.offset.click.left <= this.containment[ 2 ] ) ? 27394 left : 27395 ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ? 27396 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : 27397 left; 27398 } 27399 27400 } 27401 27402 return { 27403 top: ( 27404 27405 // The absolute mouse position 27406 pageY - 27407 27408 // Click offset (relative to the element) 27409 this.offset.click.top - 27410 27411 // Only for relative positioned nodes: Relative offset from element to offset parent 27412 this.offset.relative.top - 27413 27414 // The offsetParent's offset without borders (offset + border) 27415 this.offset.parent.top + 27416 ( ( this.cssPosition === "fixed" ? 27417 -this.scrollParent.scrollTop() : 27418 ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) ) 27419 ), 27420 left: ( 27421 27422 // The absolute mouse position 27423 pageX - 27424 27425 // Click offset (relative to the element) 27426 this.offset.click.left - 27427 27428 // Only for relative positioned nodes: Relative offset from element to offset parent 27429 this.offset.relative.left - 27430 27431 // The offsetParent's offset without borders (offset + border) 27432 this.offset.parent.left + 27433 ( ( this.cssPosition === "fixed" ? 27434 -this.scrollParent.scrollLeft() : 27435 scrollIsRootNode ? 0 : scroll.scrollLeft() ) ) 27436 ) 27437 }; 27438 27439 }, 27440 27441 _rearrange: function( event, i, a, hardRefresh ) { 27442 27443 if ( a ) { 27444 a[ 0 ].appendChild( this.placeholder[ 0 ] ); 27445 } else { 27446 i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ], 27447 ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) ); 27448 } 27449 27450 //Various things done here to improve the performance: 27451 // 1. we create a setTimeout, that calls refreshPositions 27452 // 2. on the instance, we have a counter variable, that get's higher after every append 27453 // 3. on the local scope, we copy the counter variable, and check in the timeout, 27454 // if it's still the same 27455 // 4. this lets only the last addition to the timeout stack through 27456 this.counter = this.counter ? ++this.counter : 1; 27457 var counter = this.counter; 27458 27459 this._delay( function() { 27460 if ( counter === this.counter ) { 27461 27462 //Precompute after each DOM insertion, NOT on mousemove 27463 this.refreshPositions( !hardRefresh ); 27464 } 27465 } ); 27466 27467 }, 27468 27469 _clear: function( event, noPropagation ) { 27470 27471 this.reverting = false; 27472 27473 // We delay all events that have to be triggered to after the point where the placeholder 27474 // has been removed and everything else normalized again 27475 var i, 27476 delayedTriggers = []; 27477 27478 // We first have to update the dom position of the actual currentItem 27479 // Note: don't do it if the current item is already removed (by a user), or it gets 27480 // reappended (see #4088) 27481 if ( !this._noFinalSort && this.currentItem.parent().length ) { 27482 this.placeholder.before( this.currentItem ); 27483 } 27484 this._noFinalSort = null; 27485 27486 if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) { 27487 for ( i in this._storedCSS ) { 27488 if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) { 27489 this._storedCSS[ i ] = ""; 27490 } 27491 } 27492 this.currentItem.css( this._storedCSS ); 27493 this._removeClass( this.currentItem, "ui-sortable-helper" ); 27494 } else { 27495 this.currentItem.show(); 27496 } 27497 27498 if ( this.fromOutside && !noPropagation ) { 27499 delayedTriggers.push( function( event ) { 27500 this._trigger( "receive", event, this._uiHash( this.fromOutside ) ); 27501 } ); 27502 } 27503 if ( ( this.fromOutside || 27504 this.domPosition.prev !== 27505 this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] || 27506 this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) { 27507 27508 // Trigger update callback if the DOM position has changed 27509 delayedTriggers.push( function( event ) { 27510 this._trigger( "update", event, this._uiHash() ); 27511 } ); 27512 } 27513 27514 // Check if the items Container has Changed and trigger appropriate 27515 // events. 27516 if ( this !== this.currentContainer ) { 27517 if ( !noPropagation ) { 27518 delayedTriggers.push( function( event ) { 27519 this._trigger( "remove", event, this._uiHash() ); 27520 } ); 27521 delayedTriggers.push( ( function( c ) { 27522 return function( event ) { 27523 c._trigger( "receive", event, this._uiHash( this ) ); 27524 }; 27525 } ).call( this, this.currentContainer ) ); 27526 delayedTriggers.push( ( function( c ) { 27527 return function( event ) { 27528 c._trigger( "update", event, this._uiHash( this ) ); 27529 }; 27530 } ).call( this, this.currentContainer ) ); 27531 } 27532 } 27533 27534 //Post events to containers 27535 function delayEvent( type, instance, container ) { 27536 return function( event ) { 27537 container._trigger( type, event, instance._uiHash( instance ) ); 27538 }; 27539 } 27540 for ( i = this.containers.length - 1; i >= 0; i-- ) { 27541 if ( !noPropagation ) { 27542 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); 27543 } 27544 if ( this.containers[ i ].containerCache.over ) { 27545 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); 27546 this.containers[ i ].containerCache.over = 0; 27547 } 27548 } 27549 27550 //Do what was originally in plugins 27551 if ( this._storedStylesheet ) { 27552 this._storedStylesheet.remove(); 27553 this._storedStylesheet = null; 27554 } 27555 if ( this._storedOpacity ) { 27556 this.helper.css( "opacity", this._storedOpacity ); 27557 } 27558 if ( this._storedZIndex ) { 27559 this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex ); 27560 } 27561 27562 this.dragging = false; 27563 27564 if ( !noPropagation ) { 27565 this._trigger( "beforeStop", event, this._uiHash() ); 27566 } 27567 27568 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, 27569 // it unbinds ALL events from the original node! 27570 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] ); 27571 27572 if ( !this.cancelHelperRemoval ) { 27573 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { 27574 this.helper.remove(); 27575 } 27576 this.helper = null; 27577 } 27578 27579 if ( !noPropagation ) { 27580 for ( i = 0; i < delayedTriggers.length; i++ ) { 27581 27582 // Trigger all delayed events 27583 delayedTriggers[ i ].call( this, event ); 27584 } 27585 this._trigger( "stop", event, this._uiHash() ); 27586 } 27587 27588 this.fromOutside = false; 27589 return !this.cancelHelperRemoval; 27590 27591 }, 27592 27593 _trigger: function() { 27594 if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) { 27595 this.cancel(); 27596 } 27597 }, 27598 27599 _uiHash: function( _inst ) { 27600 var inst = _inst || this; 27601 return { 27602 helper: inst.helper, 27603 placeholder: inst.placeholder || $( [] ), 27604 position: inst.position, 27605 originalPosition: inst.originalPosition, 27606 offset: inst.positionAbs, 27607 item: inst.currentItem, 27608 sender: _inst ? _inst.element : null 27609 }; 27610 } 27611 27612} ); 27613 27614 27615/*! 27616 * jQuery UI Spinner 1.14.1 27617 * https://jqueryui.com 27618 * 27619 * Copyright OpenJS Foundation and other contributors 27620 * Released under the MIT license. 27621 * https://jquery.org/license 27622 */ 27623 27624//>>label: Spinner 27625//>>group: Widgets 27626//>>description: Displays buttons to easily input numbers via the keyboard or mouse. 27627//>>docs: https://api.jqueryui.com/spinner/ 27628//>>demos: https://jqueryui.com/spinner/ 27629//>>css.structure: ../../themes/base/core.css 27630//>>css.structure: ../../themes/base/spinner.css 27631//>>css.theme: ../../themes/base/theme.css 27632 27633 27634function spinnerModifier( fn ) { 27635 return function() { 27636 var previous = this.element.val(); 27637 fn.apply( this, arguments ); 27638 this._refresh(); 27639 if ( previous !== this.element.val() ) { 27640 this._trigger( "change" ); 27641 } 27642 }; 27643} 27644 27645$.widget( "ui.spinner", { 27646 version: "1.14.1", 27647 defaultElement: "<input>", 27648 widgetEventPrefix: "spin", 27649 options: { 27650 classes: { 27651 "ui-spinner": "ui-corner-all", 27652 "ui-spinner-down": "ui-corner-br", 27653 "ui-spinner-up": "ui-corner-tr" 27654 }, 27655 culture: null, 27656 icons: { 27657 down: "ui-icon-triangle-1-s", 27658 up: "ui-icon-triangle-1-n" 27659 }, 27660 incremental: true, 27661 max: null, 27662 min: null, 27663 numberFormat: null, 27664 page: 10, 27665 step: 1, 27666 27667 change: null, 27668 spin: null, 27669 start: null, 27670 stop: null 27671 }, 27672 27673 _create: function() { 27674 27675 // handle string values that need to be parsed 27676 this._setOption( "max", this.options.max ); 27677 this._setOption( "min", this.options.min ); 27678 this._setOption( "step", this.options.step ); 27679 27680 // Only format if there is a value, prevents the field from being marked 27681 // as invalid in Firefox, see #9573. 27682 if ( this.value() !== "" ) { 27683 27684 // Format the value, but don't constrain. 27685 this._value( this.element.val(), true ); 27686 } 27687 27688 this._draw(); 27689 this._on( this._events ); 27690 this._refresh(); 27691 27692 // Turning off autocomplete prevents the browser from remembering the 27693 // value when navigating through history, so we re-enable autocomplete 27694 // if the page is unloaded before the widget is destroyed. #7790 27695 this._on( this.window, { 27696 beforeunload: function() { 27697 this.element.removeAttr( "autocomplete" ); 27698 } 27699 } ); 27700 }, 27701 27702 _getCreateOptions: function() { 27703 var options = this._super(); 27704 var element = this.element; 27705 27706 $.each( [ "min", "max", "step" ], function( i, option ) { 27707 var value = element.attr( option ); 27708 if ( value != null && value.length ) { 27709 options[ option ] = value; 27710 } 27711 } ); 27712 27713 return options; 27714 }, 27715 27716 _events: { 27717 keydown: function( event ) { 27718 if ( this._start( event ) && this._keydown( event ) ) { 27719 event.preventDefault(); 27720 } 27721 }, 27722 keyup: "_stop", 27723 focus: function() { 27724 this.previous = this.element.val(); 27725 }, 27726 blur: function( event ) { 27727 this._stop(); 27728 this._refresh(); 27729 if ( this.previous !== this.element.val() ) { 27730 this._trigger( "change", event ); 27731 } 27732 }, 27733 mousewheel: function( event, delta ) { 27734 var activeElement = this.document[ 0 ].activeElement; 27735 var isActive = this.element[ 0 ] === activeElement; 27736 27737 if ( !isActive || !delta ) { 27738 return; 27739 } 27740 27741 if ( !this.spinning && !this._start( event ) ) { 27742 return false; 27743 } 27744 27745 this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event ); 27746 clearTimeout( this.mousewheelTimer ); 27747 this.mousewheelTimer = this._delay( function() { 27748 if ( this.spinning ) { 27749 this._stop( event ); 27750 } 27751 }, 100 ); 27752 event.preventDefault(); 27753 }, 27754 "mousedown .ui-spinner-button": function( event ) { 27755 var previous; 27756 27757 // We never want the buttons to have focus; whenever the user is 27758 // interacting with the spinner, the focus should be on the input. 27759 // If the input is focused then this.previous is properly set from 27760 // when the input first received focus. If the input is not focused 27761 // then we need to set this.previous based on the value before spinning. 27762 previous = this.element[ 0 ] === this.document[ 0 ].activeElement ? 27763 this.previous : this.element.val(); 27764 function checkFocus() { 27765 var isActive = this.element[ 0 ] === this.document[ 0 ].activeElement; 27766 if ( !isActive ) { 27767 this.element.trigger( "focus" ); 27768 this.previous = previous; 27769 } 27770 } 27771 27772 // Ensure focus is on (or stays on) the text field 27773 event.preventDefault(); 27774 checkFocus.call( this ); 27775 27776 if ( this._start( event ) === false ) { 27777 return; 27778 } 27779 27780 this._repeat( null, $( event.currentTarget ) 27781 .hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 27782 }, 27783 "mouseup .ui-spinner-button": "_stop", 27784 "mouseenter .ui-spinner-button": function( event ) { 27785 27786 // button will add ui-state-active if mouse was down while mouseleave and kept down 27787 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { 27788 return; 27789 } 27790 27791 if ( this._start( event ) === false ) { 27792 return false; 27793 } 27794 this._repeat( null, $( event.currentTarget ) 27795 .hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 27796 }, 27797 27798 // TODO: do we really want to consider this a stop? 27799 // shouldn't we just stop the repeater and wait until mouseup before 27800 // we trigger the stop event? 27801 "mouseleave .ui-spinner-button": "_stop" 27802 }, 27803 27804 // Support mobile enhanced option and make backcompat more sane 27805 _enhance: function() { 27806 this.uiSpinner = this.element 27807 .attr( "autocomplete", "off" ) 27808 .wrap( "<span>" ) 27809 .parent() 27810 27811 // Add buttons 27812 .append( 27813 "<a></a><a></a>" 27814 ); 27815 }, 27816 27817 _draw: function() { 27818 this._enhance(); 27819 27820 this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" ); 27821 this._addClass( "ui-spinner-input" ); 27822 27823 this.element.attr( "role", "spinbutton" ); 27824 27825 // Button bindings 27826 this.buttons = this.uiSpinner.children( "a" ) 27827 .attr( "tabIndex", -1 ) 27828 .attr( "aria-hidden", true ) 27829 .button( { 27830 classes: { 27831 "ui-button": "" 27832 } 27833 } ); 27834 27835 // TODO: Right now button does not support classes this is already updated in button PR 27836 this._removeClass( this.buttons, "ui-corner-all" ); 27837 27838 this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" ); 27839 this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" ); 27840 this.buttons.first().button( { 27841 "icon": this.options.icons.up, 27842 "showLabel": false 27843 } ); 27844 this.buttons.last().button( { 27845 "icon": this.options.icons.down, 27846 "showLabel": false 27847 } ); 27848 27849 // IE 6 doesn't understand height: 50% for the buttons 27850 // unless the wrapper has an explicit height 27851 if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) && 27852 this.uiSpinner.height() > 0 ) { 27853 this.uiSpinner.height( this.uiSpinner.height() ); 27854 } 27855 }, 27856 27857 _keydown: function( event ) { 27858 var options = this.options, 27859 keyCode = $.ui.keyCode; 27860 27861 switch ( event.keyCode ) { 27862 case keyCode.UP: 27863 this._repeat( null, 1, event ); 27864 return true; 27865 case keyCode.DOWN: 27866 this._repeat( null, -1, event ); 27867 return true; 27868 case keyCode.PAGE_UP: 27869 this._repeat( null, options.page, event ); 27870 return true; 27871 case keyCode.PAGE_DOWN: 27872 this._repeat( null, -options.page, event ); 27873 return true; 27874 } 27875 27876 return false; 27877 }, 27878 27879 _start: function( event ) { 27880 if ( !this.spinning && this._trigger( "start", event ) === false ) { 27881 return false; 27882 } 27883 27884 if ( !this.counter ) { 27885 this.counter = 1; 27886 } 27887 this.spinning = true; 27888 return true; 27889 }, 27890 27891 _repeat: function( i, steps, event ) { 27892 i = i || 500; 27893 27894 clearTimeout( this.timer ); 27895 this.timer = this._delay( function() { 27896 this._repeat( 40, steps, event ); 27897 }, i ); 27898 27899 this._spin( steps * this.options.step, event ); 27900 }, 27901 27902 _spin: function( step, event ) { 27903 var value = this.value() || 0; 27904 27905 if ( !this.counter ) { 27906 this.counter = 1; 27907 } 27908 27909 value = this._adjustValue( value + step * this._increment( this.counter ) ); 27910 27911 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) { 27912 this._value( value ); 27913 this.counter++; 27914 } 27915 }, 27916 27917 _increment: function( i ) { 27918 var incremental = this.options.incremental; 27919 27920 if ( incremental ) { 27921 return typeof incremental === "function" ? 27922 incremental( i ) : 27923 Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 ); 27924 } 27925 27926 return 1; 27927 }, 27928 27929 _precision: function() { 27930 var precision = this._precisionOf( this.options.step ); 27931 if ( this.options.min !== null ) { 27932 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 27933 } 27934 return precision; 27935 }, 27936 27937 _precisionOf: function( num ) { 27938 var str = num.toString(), 27939 decimal = str.indexOf( "." ); 27940 return decimal === -1 ? 0 : str.length - decimal - 1; 27941 }, 27942 27943 _adjustValue: function( value ) { 27944 var base, aboveMin, 27945 options = this.options; 27946 27947 // Make sure we're at a valid step 27948 // - find out where we are relative to the base (min or 0) 27949 base = options.min !== null ? options.min : 0; 27950 aboveMin = value - base; 27951 27952 // - round to the nearest step 27953 aboveMin = Math.round( aboveMin / options.step ) * options.step; 27954 27955 // - rounding is based on 0, so adjust back to our base 27956 value = base + aboveMin; 27957 27958 // Fix precision from bad JS floating point math 27959 value = parseFloat( value.toFixed( this._precision() ) ); 27960 27961 // Clamp the value 27962 if ( options.max !== null && value > options.max ) { 27963 return options.max; 27964 } 27965 if ( options.min !== null && value < options.min ) { 27966 return options.min; 27967 } 27968 27969 return value; 27970 }, 27971 27972 _stop: function( event ) { 27973 if ( !this.spinning ) { 27974 return; 27975 } 27976 27977 clearTimeout( this.timer ); 27978 clearTimeout( this.mousewheelTimer ); 27979 this.counter = 0; 27980 this.spinning = false; 27981 this._trigger( "stop", event ); 27982 }, 27983 27984 _setOption: function( key, value ) { 27985 var prevValue, first, last; 27986 27987 if ( key === "culture" || key === "numberFormat" ) { 27988 prevValue = this._parse( this.element.val() ); 27989 this.options[ key ] = value; 27990 this.element.val( this._format( prevValue ) ); 27991 return; 27992 } 27993
vendor: 6,415 bytes, lines 27994-28247
27994 if ( key === "max" || key === "min" || key === "step" ) { 27995 if ( typeof value === "string" ) { 27996 value = this._parse( value ); 27997 } 27998 } 27999 if ( key === "icons" ) { 28000 first = this.buttons.first().find( ".ui-icon" ); 28001 this._removeClass( first, null, this.options.icons.up ); 28002 this._addClass( first, null, value.up ); 28003 last = this.buttons.last().find( ".ui-icon" ); 28004 this._removeClass( last, null, this.options.icons.down ); 28005 this._addClass( last, null, value.down ); 28006 } 28007 28008 this._super( key, value ); 28009 }, 28010 28011 _setOptionDisabled: function( value ) { 28012 this._super( value ); 28013 28014 this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value ); 28015 this.element.prop( "disabled", !!value ); 28016 this.buttons.button( value ? "disable" : "enable" ); 28017 }, 28018 28019 _setOptions: spinnerModifier( function( options ) { 28020 this._super( options ); 28021 } ), 28022 28023 _parse: function( val ) { 28024 if ( typeof val === "string" && val !== "" ) { 28025 val = window.Globalize && this.options.numberFormat ? 28026 Globalize.parseFloat( val, 10, this.options.culture ) : +val; 28027 } 28028 return val === "" || isNaN( val ) ? null : val; 28029 }, 28030 28031 _format: function( value ) { 28032 if ( value === "" ) { 28033 return ""; 28034 } 28035 return window.Globalize && this.options.numberFormat ? 28036 Globalize.format( value, this.options.numberFormat, this.options.culture ) : 28037 value; 28038 }, 28039 28040 _refresh: function() { 28041 this.element.attr( { 28042 "aria-valuemin": this.options.min, 28043 "aria-valuemax": this.options.max, 28044 28045 // TODO: what should we do with values that can't be parsed? 28046 "aria-valuenow": this._parse( this.element.val() ) 28047 } ); 28048 }, 28049 28050 isValid: function() { 28051 var value = this.value(); 28052 28053 // Null is invalid 28054 if ( value === null ) { 28055 return false; 28056 } 28057 28058 // If value gets adjusted, it's invalid 28059 return value === this._adjustValue( value ); 28060 }, 28061 28062 // Update the value without triggering change 28063 _value: function( value, allowAny ) { 28064 var parsed; 28065 if ( value !== "" ) { 28066 parsed = this._parse( value ); 28067 if ( parsed !== null ) { 28068 if ( !allowAny ) { 28069 parsed = this._adjustValue( parsed ); 28070 } 28071 value = this._format( parsed ); 28072 } 28073 } 28074 this.element.val( value ); 28075 this._refresh(); 28076 }, 28077 28078 _destroy: function() { 28079 this.element 28080 .prop( "disabled", false ) 28081 .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" ); 28082 28083 this.uiSpinner.replaceWith( this.element ); 28084 }, 28085 28086 stepUp: spinnerModifier( function( steps ) { 28087 this._stepUp( steps ); 28088 } ), 28089 _stepUp: function( steps ) { 28090 if ( this._start() ) { 28091 this._spin( ( steps || 1 ) * this.options.step ); 28092 this._stop(); 28093 } 28094 }, 28095 28096 stepDown: spinnerModifier( function( steps ) { 28097 this._stepDown( steps ); 28098 } ), 28099 _stepDown: function( steps ) { 28100 if ( this._start() ) { 28101 this._spin( ( steps || 1 ) * -this.options.step ); 28102 this._stop(); 28103 } 28104 }, 28105 28106 pageUp: spinnerModifier( function( pages ) { 28107 this._stepUp( ( pages || 1 ) * this.options.page ); 28108 } ), 28109 28110 pageDown: spinnerModifier( function( pages ) { 28111 this._stepDown( ( pages || 1 ) * this.options.page ); 28112 } ), 28113 28114 value: function( newVal ) { 28115 if ( !arguments.length ) { 28116 return this._parse( this.element.val() ); 28117 } 28118 spinnerModifier( this._value ).call( this, newVal ); 28119 }, 28120 28121 widget: function() { 28122 return this.uiSpinner; 28123 } 28124} ); 28125 28126// DEPRECATED 28127// TODO: switch return back to widget declaration at top of file when this is removed 28128if ( $.uiBackCompat === true ) { 28129 28130 // Backcompat for spinner html extension points 28131 $.widget( "ui.spinner", $.ui.spinner, { 28132 _enhance: function() { 28133 this.uiSpinner = this.element 28134 .attr( "autocomplete", "off" ) 28135 .wrap( this._uiSpinnerHtml() ) 28136 .parent() 28137 28138 // Add buttons 28139 .append( this._buttonHtml() ); 28140 }, 28141 _uiSpinnerHtml: function() { 28142 return "<span>"; 28143 }, 28144 28145 _buttonHtml: function() { 28146 return "<a></a><a></a>"; 28147 } 28148 } ); 28149} 28150 28151var widgetsSpinner = $.ui.spinner; 28152 28153 28154/*! 28155 * jQuery UI Tabs 1.14.1 28156 * https://jqueryui.com 28157 * 28158 * Copyright OpenJS Foundation and other contributors 28159 * Released under the MIT license. 28160 * https://jquery.org/license 28161 */ 28162 28163//>>label: Tabs 28164//>>group: Widgets 28165//>>description: Transforms a set of container elements into a tab structure. 28166//>>docs: https://api.jqueryui.com/tabs/ 28167//>>demos: https://jqueryui.com/tabs/ 28168//>>css.structure: ../../themes/base/core.css 28169//>>css.structure: ../../themes/base/tabs.css 28170//>>css.theme: ../../themes/base/theme.css 28171 28172 28173$.widget( "ui.tabs", { 28174 version: "1.14.1", 28175 delay: 300, 28176 options: { 28177 active: null, 28178 classes: { 28179 "ui-tabs": "ui-corner-all", 28180 "ui-tabs-nav": "ui-corner-all", 28181 "ui-tabs-panel": "ui-corner-bottom", 28182 "ui-tabs-tab": "ui-corner-top" 28183 }, 28184 collapsible: false, 28185 event: "click", 28186 heightStyle: "content", 28187 hide: null, 28188 show: null, 28189 28190 // Callbacks 28191 activate: null, 28192 beforeActivate: null, 28193 beforeLoad: null, 28194 load: null 28195 }, 28196 28197 _isLocal: ( function() { 28198 var rhash = /#.*$/; 28199 28200 return function( anchor ) { 28201 var anchorUrl, locationUrl; 28202 28203 anchorUrl = anchor.href.replace( rhash, "" ); 28204 locationUrl = location.href.replace( rhash, "" ); 28205 28206 // Decoding may throw an error if the URL isn't UTF-8 (#9518) 28207 try { 28208 anchorUrl = decodeURIComponent( anchorUrl ); 28209 } catch ( error ) {} 28210 try { 28211 locationUrl = decodeURIComponent( locationUrl ); 28212 } catch ( error ) {} 28213 28214 return anchor.hash.length > 1 && anchorUrl === locationUrl; 28215 }; 28216 } )(), 28217 28218 _create: function() { 28219 var that = this, 28220 options = this.options; 28221 28222 this.running = false; 28223 28224 this._addClass( "ui-tabs", "ui-widget ui-widget-content" ); 28225 this._toggleClass( "ui-tabs-collapsible", null, options.collapsible ); 28226 28227 this._processTabs(); 28228 options.active = this._initialActive(); 28229 28230 // Take disabling tabs via class attribute from HTML 28231 // into account and update option properly. 28232 if ( Array.isArray( options.disabled ) ) { 28233 options.disabled = $.uniqueSort( options.disabled.concat( 28234 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { 28235 return that.tabs.index( li ); 28236 } ) 28237 ) ).sort(); 28238 } 28239 28240 // Check for length avoids error when initializing empty list 28241 if ( this.options.active !== false && this.anchors.length ) { 28242 this.active = this._findActive( options.active ); 28243 } else { 28244 this.active = $(); 28245 } 28246 28247 this._refresh();
vendor: 30,881 bytes, lines 28248-29378
28248 28249 if ( this.active.length ) { 28250 this.load( options.active ); 28251 } 28252 }, 28253 28254 _initialActive: function() { 28255 var active = this.options.active, 28256 collapsible = this.options.collapsible, 28257 locationHashDecoded = decodeURIComponent( location.hash.substring( 1 ) ); 28258 28259 if ( active === null ) { 28260 28261 // check the fragment identifier in the URL 28262 if ( locationHashDecoded ) { 28263 this.tabs.each( function( i, tab ) { 28264 if ( $( tab ).attr( "aria-controls" ) === locationHashDecoded ) { 28265 active = i; 28266 return false; 28267 } 28268 } ); 28269 } 28270 28271 // Check for a tab marked active via a class 28272 if ( active === null ) { 28273 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); 28274 } 28275 28276 // No active tab, set to false 28277 if ( active === null || active === -1 ) { 28278 active = this.tabs.length ? 0 : false; 28279 } 28280 } 28281 28282 // Handle numbers: negative, out of range 28283 if ( active !== false ) { 28284 active = this.tabs.index( this.tabs.eq( active ) ); 28285 if ( active === -1 ) { 28286 active = collapsible ? false : 0; 28287 } 28288 } 28289 28290 // Don't allow collapsible: false and active: false 28291 if ( !collapsible && active === false && this.anchors.length ) { 28292 active = 0; 28293 } 28294 28295 return active; 28296 }, 28297 28298 _getCreateEventData: function() { 28299 return { 28300 tab: this.active, 28301 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) 28302 }; 28303 }, 28304 28305 _tabKeydown: function( event ) { 28306 var focusedTab = $( this.document[ 0 ].activeElement ).closest( "li" ), 28307 selectedIndex = this.tabs.index( focusedTab ), 28308 goingForward = true; 28309 28310 if ( this._handlePageNav( event ) ) { 28311 return; 28312 } 28313 28314 switch ( event.keyCode ) { 28315 case $.ui.keyCode.RIGHT: 28316 case $.ui.keyCode.DOWN: 28317 selectedIndex++; 28318 break; 28319 case $.ui.keyCode.UP: 28320 case $.ui.keyCode.LEFT: 28321 goingForward = false; 28322 selectedIndex--; 28323 break; 28324 case $.ui.keyCode.END: 28325 selectedIndex = this.anchors.length - 1; 28326 break; 28327 case $.ui.keyCode.HOME: 28328 selectedIndex = 0; 28329 break; 28330 case $.ui.keyCode.SPACE: 28331 28332 // Activate only, no collapsing 28333 event.preventDefault(); 28334 clearTimeout( this.activating ); 28335 this._activate( selectedIndex ); 28336 return; 28337 case $.ui.keyCode.ENTER: 28338 28339 // Toggle (cancel delayed activation, allow collapsing) 28340 event.preventDefault(); 28341 clearTimeout( this.activating ); 28342 28343 // Determine if we should collapse or activate 28344 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); 28345 return; 28346 default: 28347 return; 28348 } 28349 28350 // Focus the appropriate tab, based on which key was pressed 28351 event.preventDefault(); 28352 clearTimeout( this.activating ); 28353 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); 28354 28355 // Navigating with control/command key will prevent automatic activation 28356 if ( !event.ctrlKey && !event.metaKey ) { 28357 28358 // Update aria-selected immediately so that AT think the tab is already selected. 28359 // Otherwise AT may confuse the user by stating that they need to activate the tab, 28360 // but the tab will already be activated by the time the announcement finishes. 28361 focusedTab.attr( "aria-selected", "false" ); 28362 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); 28363 28364 this.activating = this._delay( function() { 28365 this.option( "active", selectedIndex ); 28366 }, this.delay ); 28367 } 28368 }, 28369 28370 _panelKeydown: function( event ) { 28371 if ( this._handlePageNav( event ) ) { 28372 return; 28373 } 28374 28375 // Ctrl+up moves focus to the current tab 28376 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { 28377 event.preventDefault(); 28378 this.active.trigger( "focus" ); 28379 } 28380 }, 28381 28382 // Alt+page up/down moves focus to the previous/next tab (and activates) 28383 _handlePageNav: function( event ) { 28384 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { 28385 this._activate( this._focusNextTab( this.options.active - 1, false ) ); 28386 return true; 28387 } 28388 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { 28389 this._activate( this._focusNextTab( this.options.active + 1, true ) ); 28390 return true; 28391 } 28392 }, 28393 28394 _findNextTab: function( index, goingForward ) { 28395 var lastTabIndex = this.tabs.length - 1; 28396 28397 function constrain() { 28398 if ( index > lastTabIndex ) { 28399 index = 0; 28400 } 28401 if ( index < 0 ) { 28402 index = lastTabIndex; 28403 } 28404 return index; 28405 } 28406 28407 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { 28408 index = goingForward ? index + 1 : index - 1; 28409 } 28410 28411 return index; 28412 }, 28413 28414 _focusNextTab: function( index, goingForward ) { 28415 index = this._findNextTab( index, goingForward ); 28416 this.tabs.eq( index ).trigger( "focus" ); 28417 return index; 28418 }, 28419 28420 _setOption: function( key, value ) { 28421 if ( key === "active" ) { 28422 28423 // _activate() will handle invalid values and update this.options 28424 this._activate( value ); 28425 return; 28426 } 28427 28428 this._super( key, value ); 28429 28430 if ( key === "collapsible" ) { 28431 this._toggleClass( "ui-tabs-collapsible", null, value ); 28432 28433 // Setting collapsible: false while collapsed; open first panel 28434 if ( !value && this.options.active === false ) { 28435 this._activate( 0 ); 28436 } 28437 } 28438 28439 if ( key === "event" ) { 28440 this._setupEvents( value ); 28441 } 28442 28443 if ( key === "heightStyle" ) { 28444 this._setupHeightStyle( value ); 28445 } 28446 }, 28447 28448 refresh: function() { 28449 var options = this.options, 28450 lis = this.tablist.children( ":has(a[href])" ); 28451 28452 // Get disabled tabs from class attribute from HTML 28453 // this will get converted to a boolean if needed in _refresh() 28454 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { 28455 return lis.index( tab ); 28456 } ); 28457 28458 this._processTabs(); 28459 28460 // Was collapsed or no tabs 28461 if ( options.active === false || !this.anchors.length ) { 28462 options.active = false; 28463 this.active = $(); 28464 28465 // was active, but active tab is gone 28466 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { 28467 28468 // all remaining tabs are disabled 28469 if ( this.tabs.length === options.disabled.length ) { 28470 options.active = false; 28471 this.active = $(); 28472 28473 // activate previous tab 28474 } else { 28475 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); 28476 } 28477 28478 // was active, active tab still exists 28479 } else { 28480 28481 // make sure active index is correct 28482 options.active = this.tabs.index( this.active ); 28483 } 28484 28485 this._refresh(); 28486 }, 28487 28488 _refresh: function() { 28489 this._setOptionDisabled( this.options.disabled ); 28490 this._setupEvents( this.options.event ); 28491 this._setupHeightStyle( this.options.heightStyle ); 28492 28493 this.tabs.not( this.active ).attr( { 28494 "aria-selected": "false", 28495 "aria-expanded": "false", 28496 tabIndex: -1 28497 } ); 28498 this.panels.not( this._getPanelForTab( this.active ) ) 28499 .hide() 28500 .attr( { 28501 "aria-hidden": "true" 28502 } ); 28503 28504 // Make sure one tab is in the tab order 28505 if ( !this.active.length ) { 28506 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); 28507 } else { 28508 this.active 28509 .attr( { 28510 "aria-selected": "true", 28511 "aria-expanded": "true", 28512 tabIndex: 0 28513 } ); 28514 this._addClass( this.active, "ui-tabs-active", "ui-state-active" ); 28515 this._getPanelForTab( this.active ) 28516 .show() 28517 .attr( { 28518 "aria-hidden": "false" 28519 } ); 28520 } 28521 }, 28522 28523 _processTabs: function() { 28524 var that = this, 28525 prevTabs = this.tabs, 28526 prevAnchors = this.anchors, 28527 prevPanels = this.panels; 28528 28529 this.tablist = this._getList().attr( "role", "tablist" ); 28530 this._addClass( this.tablist, "ui-tabs-nav", 28531 "ui-helper-reset ui-helper-clearfix ui-widget-header" ); 28532 28533 // Prevent users from focusing disabled tabs via click 28534 this.tablist 28535 .on( "mousedown" + this.eventNamespace, "> li", function( event ) { 28536 if ( $( this ).is( ".ui-state-disabled" ) ) { 28537 event.preventDefault(); 28538 } 28539 } ); 28540 28541 this.tabs = this.tablist.find( "> li:has(a[href])" ) 28542 .attr( { 28543 role: "tab", 28544 tabIndex: -1 28545 } ); 28546 this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" ); 28547 28548 this.anchors = this.tabs.map( function() { 28549 return $( "a", this )[ 0 ]; 28550 } ) 28551 .attr( { 28552 tabIndex: -1 28553 } ); 28554 this._addClass( this.anchors, "ui-tabs-anchor" ); 28555 28556 this.panels = $(); 28557 28558 this.anchors.each( function( i, anchor ) { 28559 var selector, panel, panelId, 28560 anchorId = $( anchor ).uniqueId().attr( "id" ), 28561 tab = $( anchor ).closest( "li" ), 28562 originalAriaControls = tab.attr( "aria-controls" ); 28563 28564 // Inline tab 28565 if ( that._isLocal( anchor ) ) { 28566 selector = decodeURIComponent( anchor.hash ); 28567 panelId = selector.substring( 1 ); 28568 panel = that.element.find( "#" + CSS.escape( panelId ) ); 28569 28570 // remote tab 28571 } else { 28572 28573 // If the tab doesn't already have aria-controls, 28574 // generate an id by using a throw-away element 28575 panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id; 28576 selector = "#" + panelId; 28577 panel = that.element.find( selector ); 28578 if ( !panel.length ) { 28579 panel = that._createPanel( panelId ); 28580 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); 28581 } 28582 panel.attr( "aria-live", "polite" ); 28583 } 28584 28585 if ( panel.length ) { 28586 that.panels = that.panels.add( panel ); 28587 } 28588 if ( originalAriaControls ) { 28589 tab.data( "ui-tabs-aria-controls", originalAriaControls ); 28590 } 28591 tab.attr( { 28592 "aria-controls": panelId, 28593 "aria-labelledby": anchorId 28594 } ); 28595 panel.attr( "aria-labelledby", anchorId ); 28596 } ); 28597 28598 this.panels.attr( "role", "tabpanel" ); 28599 this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" ); 28600 28601 // Avoid memory leaks (#10056) 28602 if ( prevTabs ) { 28603 this._off( prevTabs.not( this.tabs ) ); 28604 this._off( prevAnchors.not( this.anchors ) ); 28605 this._off( prevPanels.not( this.panels ) ); 28606 } 28607 }, 28608 28609 // Allow overriding how to find the list for rare usage scenarios (#7715) 28610 _getList: function() { 28611 return this.tablist || this.element.find( "ol, ul" ).eq( 0 ); 28612 }, 28613 28614 _createPanel: function( id ) { 28615 return $( "<div>" ) 28616 .attr( "id", id ) 28617 .data( "ui-tabs-destroy", true ); 28618 }, 28619 28620 _setOptionDisabled: function( disabled ) { 28621 var currentItem, li, i; 28622 28623 if ( Array.isArray( disabled ) ) { 28624 if ( !disabled.length ) { 28625 disabled = false; 28626 } else if ( disabled.length === this.anchors.length ) { 28627 disabled = true; 28628 } 28629 } 28630 28631 // Disable tabs 28632 for ( i = 0; ( li = this.tabs[ i ] ); i++ ) { 28633 currentItem = $( li ); 28634 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { 28635 currentItem.attr( "aria-disabled", "true" ); 28636 this._addClass( currentItem, null, "ui-state-disabled" ); 28637 } else { 28638 currentItem.removeAttr( "aria-disabled" ); 28639 this._removeClass( currentItem, null, "ui-state-disabled" ); 28640 } 28641 } 28642 28643 this.options.disabled = disabled; 28644 28645 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, 28646 disabled === true ); 28647 }, 28648 28649 _setupEvents: function( event ) { 28650 var events = {}; 28651 if ( event ) { 28652 $.each( event.split( " " ), function( index, eventName ) { 28653 events[ eventName ] = "_eventHandler"; 28654 } ); 28655 } 28656 28657 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); 28658 28659 // Always prevent the default action, even when disabled 28660 this._on( true, this.anchors, { 28661 click: function( event ) { 28662 event.preventDefault(); 28663 } 28664 } ); 28665 this._on( this.anchors, events ); 28666 this._on( this.tabs, { keydown: "_tabKeydown" } ); 28667 this._on( this.panels, { keydown: "_panelKeydown" } ); 28668 28669 this._focusable( this.tabs ); 28670 this._hoverable( this.tabs ); 28671 }, 28672 28673 _setupHeightStyle: function( heightStyle ) { 28674 var maxHeight, 28675 parent = this.element.parent(); 28676 28677 if ( heightStyle === "fill" ) { 28678 maxHeight = parent.height(); 28679 maxHeight -= this.element.outerHeight() - this.element.height(); 28680 28681 this.element.siblings( ":visible" ).each( function() { 28682 var elem = $( this ), 28683 position = elem.css( "position" ); 28684 28685 if ( position === "absolute" || position === "fixed" ) { 28686 return; 28687 } 28688 maxHeight -= elem.outerHeight( true ); 28689 } ); 28690 28691 this.element.children().not( this.panels ).each( function() { 28692 maxHeight -= $( this ).outerHeight( true ); 28693 } ); 28694 28695 this.panels.each( function() { 28696 $( this ).height( Math.max( 0, maxHeight - 28697 $( this ).innerHeight() + $( this ).height() ) ); 28698 } ) 28699 .css( "overflow", "auto" ); 28700 } else if ( heightStyle === "auto" ) { 28701 maxHeight = 0; 28702 this.panels.each( function() { 28703 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 28704 } ).height( maxHeight ); 28705 } 28706 }, 28707 28708 _eventHandler: function( event ) { 28709 var options = this.options, 28710 active = this.active, 28711 anchor = $( event.currentTarget ), 28712 tab = anchor.closest( "li" ), 28713 clickedIsActive = tab[ 0 ] === active[ 0 ], 28714 collapsing = clickedIsActive && options.collapsible, 28715 toShow = collapsing ? $() : this._getPanelForTab( tab ), 28716 toHide = !active.length ? $() : this._getPanelForTab( active ), 28717 eventData = { 28718 oldTab: active, 28719 oldPanel: toHide, 28720 newTab: collapsing ? $() : tab, 28721 newPanel: toShow 28722 }; 28723 28724 event.preventDefault(); 28725 28726 if ( tab.hasClass( "ui-state-disabled" ) || 28727 28728 // tab is already loading 28729 tab.hasClass( "ui-tabs-loading" ) || 28730 28731 // can't switch durning an animation 28732 this.running || 28733 28734 // click on active header, but not collapsible 28735 ( clickedIsActive && !options.collapsible ) || 28736 28737 // allow canceling activation 28738 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 28739 return; 28740 } 28741 28742 options.active = collapsing ? false : this.tabs.index( tab ); 28743 28744 this.active = clickedIsActive ? $() : tab; 28745 if ( this.xhr ) { 28746 this.xhr.abort(); 28747 } 28748 28749 if ( !toHide.length && !toShow.length ) { 28750 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); 28751 } 28752 28753 if ( toShow.length ) { 28754 this.load( this.tabs.index( tab ), event ); 28755 } 28756 this._toggle( event, eventData ); 28757 }, 28758 28759 // Handles show/hide for selecting tabs 28760 _toggle: function( event, eventData ) { 28761 var that = this, 28762 toShow = eventData.newPanel, 28763 toHide = eventData.oldPanel; 28764 28765 this.running = true; 28766 28767 function complete() { 28768 that.running = false; 28769 that._trigger( "activate", event, eventData ); 28770 } 28771 28772 function show() { 28773 that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" ); 28774 28775 if ( toShow.length && that.options.show ) { 28776 that._show( toShow, that.options.show, complete ); 28777 } else { 28778 toShow.show(); 28779 complete(); 28780 } 28781 } 28782 28783 // Start out by hiding, then showing, then completing 28784 if ( toHide.length && this.options.hide ) { 28785 this._hide( toHide, this.options.hide, function() { 28786 that._removeClass( eventData.oldTab.closest( "li" ), 28787 "ui-tabs-active", "ui-state-active" ); 28788 show(); 28789 } ); 28790 } else { 28791 this._removeClass( eventData.oldTab.closest( "li" ), 28792 "ui-tabs-active", "ui-state-active" ); 28793 toHide.hide(); 28794 show(); 28795 } 28796 28797 toHide.attr( "aria-hidden", "true" ); 28798 eventData.oldTab.attr( { 28799 "aria-selected": "false", 28800 "aria-expanded": "false" 28801 } ); 28802 28803 // If we're switching tabs, remove the old tab from the tab order. 28804 // If we're opening from collapsed state, remove the previous tab from the tab order. 28805 // If we're collapsing, then keep the collapsing tab in the tab order. 28806 if ( toShow.length && toHide.length ) { 28807 eventData.oldTab.attr( "tabIndex", -1 ); 28808 } else if ( toShow.length ) { 28809 this.tabs.filter( function() { 28810 return $( this ).attr( "tabIndex" ) === 0; 28811 } ) 28812 .attr( "tabIndex", -1 ); 28813 } 28814 28815 toShow.attr( "aria-hidden", "false" ); 28816 eventData.newTab.attr( { 28817 "aria-selected": "true", 28818 "aria-expanded": "true", 28819 tabIndex: 0 28820 } ); 28821 }, 28822 28823 _activate: function( index ) { 28824 var anchor, 28825 active = this._findActive( index ); 28826 28827 // Trying to activate the already active panel 28828 if ( active[ 0 ] === this.active[ 0 ] ) { 28829 return; 28830 } 28831 28832 // Trying to collapse, simulate a click on the current active header 28833 if ( !active.length ) { 28834 active = this.active; 28835 } 28836 28837 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; 28838 this._eventHandler( { 28839 target: anchor, 28840 currentTarget: anchor, 28841 preventDefault: $.noop 28842 } ); 28843 }, 28844 28845 _findActive: function( index ) { 28846 return index === false ? $() : this.tabs.eq( index ); 28847 }, 28848 28849 _getIndex: function( index ) { 28850 28851 // meta-function to give users option to provide a href string instead of a numerical index. 28852 if ( typeof index === "string" ) { 28853 index = this.anchors.index( this.anchors.filter( "[href$='" + 28854 CSS.escape( index ) + "']" ) ); 28855 } 28856 28857 return index; 28858 }, 28859 28860 _destroy: function() { 28861 if ( this.xhr ) { 28862 this.xhr.abort(); 28863 } 28864 28865 this.tablist 28866 .removeAttr( "role" ) 28867 .off( this.eventNamespace ); 28868 28869 this.anchors 28870 .removeAttr( "role tabIndex" ) 28871 .removeUniqueId(); 28872 28873 this.tabs.add( this.panels ).each( function() { 28874 if ( $.data( this, "ui-tabs-destroy" ) ) { 28875 $( this ).remove(); 28876 } else { 28877 $( this ).removeAttr( "role tabIndex " + 28878 "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" ); 28879 } 28880 } ); 28881 28882 this.tabs.each( function() { 28883 var li = $( this ), 28884 prev = li.data( "ui-tabs-aria-controls" ); 28885 if ( prev ) { 28886 li 28887 .attr( "aria-controls", prev ) 28888 .removeData( "ui-tabs-aria-controls" ); 28889 } else { 28890 li.removeAttr( "aria-controls" ); 28891 } 28892 } ); 28893 28894 this.panels.show(); 28895 28896 if ( this.options.heightStyle !== "content" ) { 28897 this.panels.css( "height", "" ); 28898 } 28899 }, 28900 28901 enable: function( index ) { 28902 var disabled = this.options.disabled; 28903 if ( disabled === false ) { 28904 return; 28905 } 28906 28907 if ( index === undefined ) { 28908 disabled = false; 28909 } else { 28910 index = this._getIndex( index ); 28911 if ( Array.isArray( disabled ) ) { 28912 disabled = $.map( disabled, function( num ) { 28913 return num !== index ? num : null; 28914 } ); 28915 } else { 28916 disabled = $.map( this.tabs, function( li, num ) { 28917 return num !== index ? num : null; 28918 } ); 28919 } 28920 } 28921 this._setOptionDisabled( disabled ); 28922 }, 28923 28924 disable: function( index ) { 28925 var disabled = this.options.disabled; 28926 if ( disabled === true ) { 28927 return; 28928 } 28929 28930 if ( index === undefined ) { 28931 disabled = true; 28932 } else { 28933 index = this._getIndex( index ); 28934 if ( $.inArray( index, disabled ) !== -1 ) { 28935 return; 28936 } 28937 if ( Array.isArray( disabled ) ) { 28938 disabled = $.merge( [ index ], disabled ).sort(); 28939 } else { 28940 disabled = [ index ]; 28941 } 28942 } 28943 this._setOptionDisabled( disabled ); 28944 }, 28945 28946 load: function( index, event ) { 28947 index = this._getIndex( index ); 28948 var that = this, 28949 tab = this.tabs.eq( index ), 28950 anchor = tab.find( ".ui-tabs-anchor" ), 28951 panel = this._getPanelForTab( tab ), 28952 eventData = { 28953 tab: tab, 28954 panel: panel 28955 }, 28956 complete = function( jqXHR, status ) { 28957 if ( status === "abort" ) { 28958 that.panels.stop( false, true ); 28959 } 28960 28961 that._removeClass( tab, "ui-tabs-loading" ); 28962 panel.removeAttr( "aria-busy" ); 28963 28964 if ( jqXHR === that.xhr ) { 28965 delete that.xhr; 28966 } 28967 }; 28968 28969 // Not remote 28970 if ( this._isLocal( anchor[ 0 ] ) ) { 28971 return; 28972 } 28973 28974 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); 28975 28976 if ( this.xhr.statusText !== "canceled" ) { 28977 this._addClass( tab, "ui-tabs-loading" ); 28978 panel.attr( "aria-busy", "true" ); 28979 28980 this.xhr 28981 .done( function( response, status, jqXHR ) { 28982 panel.html( response ); 28983 that._trigger( "load", event, eventData ); 28984 28985 complete( jqXHR, status ); 28986 } ) 28987 .fail( function( jqXHR, status ) { 28988 complete( jqXHR, status ); 28989 } ); 28990 } 28991 }, 28992 28993 _ajaxSettings: function( anchor, event, eventData ) { 28994 var that = this; 28995 return { 28996 url: anchor.attr( "href" ), 28997 beforeSend: function( jqXHR, settings ) { 28998 return that._trigger( "beforeLoad", event, 28999 $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) ); 29000 } 29001 }; 29002 }, 29003 29004 _getPanelForTab: function( tab ) { 29005 var id = $( tab ).attr( "aria-controls" ); 29006 return this.element.find( "#" + CSS.escape( id ) ); 29007 } 29008} ); 29009 29010// DEPRECATED 29011// TODO: Switch return back to widget declaration at top of file when this is removed 29012if ( $.uiBackCompat === true ) { 29013 29014 // Backcompat for ui-tab class (now ui-tabs-tab) 29015 $.widget( "ui.tabs", $.ui.tabs, { 29016 _processTabs: function() { 29017 this._superApply( arguments ); 29018 this._addClass( this.tabs, "ui-tab" ); 29019 } 29020 } ); 29021} 29022 29023var widgetsTabs = $.ui.tabs; 29024 29025 29026/*! 29027 * jQuery UI Tooltip 1.14.1 29028 * https://jqueryui.com 29029 * 29030 * Copyright OpenJS Foundation and other contributors 29031 * Released under the MIT license. 29032 * https://jquery.org/license 29033 */ 29034 29035//>>label: Tooltip 29036//>>group: Widgets 29037//>>description: Shows additional information for any element on hover or focus. 29038//>>docs: https://api.jqueryui.com/tooltip/ 29039//>>demos: https://jqueryui.com/tooltip/ 29040//>>css.structure: ../../themes/base/core.css 29041//>>css.structure: ../../themes/base/tooltip.css 29042//>>css.theme: ../../themes/base/theme.css 29043 29044 29045$.widget( "ui.tooltip", { 29046 version: "1.14.1", 29047 options: { 29048 classes: { 29049 "ui-tooltip": "ui-corner-all ui-widget-shadow" 29050 }, 29051 content: function() { 29052 var title = $( this ).attr( "title" ); 29053 29054 // Escape title, since we're going from an attribute to raw HTML 29055 return $( "<a>" ).text( title ).html(); 29056 }, 29057 hide: true, 29058 29059 // Disabled elements have inconsistent behavior across browsers (#8661) 29060 items: "[title]:not([disabled])", 29061 position: { 29062 my: "left top+15", 29063 at: "left bottom", 29064 collision: "flipfit flip" 29065 }, 29066 show: true, 29067 track: false, 29068 29069 // Callbacks 29070 close: null, 29071 open: null 29072 }, 29073 29074 _addDescribedBy: function( elem, id ) { 29075 var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ); 29076 describedby.push( id ); 29077 elem 29078 .data( "ui-tooltip-id", id ) 29079 .attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) ); 29080 }, 29081 29082 _removeDescribedBy: function( elem ) { 29083 var id = elem.data( "ui-tooltip-id" ), 29084 describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ), 29085 index = $.inArray( id, describedby ); 29086 29087 if ( index !== -1 ) { 29088 describedby.splice( index, 1 ); 29089 } 29090 29091 elem.removeData( "ui-tooltip-id" ); 29092 describedby = String.prototype.trim.call( describedby.join( " " ) ); 29093 if ( describedby ) { 29094 elem.attr( "aria-describedby", describedby ); 29095 } else { 29096 elem.removeAttr( "aria-describedby" ); 29097 } 29098 }, 29099 29100 _create: function() { 29101 this._on( { 29102 mouseover: "open", 29103 focusin: "open" 29104 } ); 29105 29106 // IDs of generated tooltips, needed for destroy 29107 this.tooltips = {}; 29108 29109 // IDs of parent tooltips where we removed the title attribute 29110 this.parents = {}; 29111 29112 // Append the aria-live region so tooltips announce correctly 29113 this.liveRegion = $( "<div>" ) 29114 .attr( { 29115 role: "log", 29116 "aria-live": "assertive", 29117 "aria-relevant": "additions" 29118 } ) 29119 .appendTo( this.document[ 0 ].body ); 29120 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" ); 29121 29122 this.disabledTitles = $( [] ); 29123 }, 29124 29125 _setOption: function( key, value ) { 29126 var that = this; 29127 29128 this._super( key, value ); 29129 29130 if ( key === "content" ) { 29131 $.each( this.tooltips, function( id, tooltipData ) { 29132 that._updateContent( tooltipData.element ); 29133 } ); 29134 } 29135 }, 29136 29137 _setOptionDisabled: function( value ) { 29138 this[ value ? "_disable" : "_enable" ](); 29139 }, 29140 29141 _disable: function() { 29142 var that = this; 29143 29144 // Close open tooltips 29145 $.each( this.tooltips, function( id, tooltipData ) { 29146 var event = $.Event( "blur" ); 29147 event.target = event.currentTarget = tooltipData.element[ 0 ]; 29148 that.close( event, true ); 29149 } ); 29150 29151 // Remove title attributes to prevent native tooltips 29152 this.disabledTitles = this.disabledTitles.add( 29153 this.element.find( this.options.items ).addBack() 29154 .filter( function() { 29155 var element = $( this ); 29156 if ( element.is( "[title]" ) ) { 29157 return element 29158 .data( "ui-tooltip-title", element.attr( "title" ) ) 29159 .removeAttr( "title" ); 29160 } 29161 } ) 29162 ); 29163 }, 29164 29165 _enable: function() { 29166 29167 // restore title attributes 29168 this.disabledTitles.each( function() { 29169 var element = $( this ); 29170 if ( element.data( "ui-tooltip-title" ) ) { 29171 element.attr( "title", element.data( "ui-tooltip-title" ) ); 29172 } 29173 } ); 29174 this.disabledTitles = $( [] ); 29175 }, 29176 29177 open: function( event ) { 29178 var that = this, 29179 target = $( event ? event.target : this.element ) 29180 29181 // we need closest here due to mouseover bubbling, 29182 // but always pointing at the same event target 29183 .closest( this.options.items ); 29184 29185 // No element to show a tooltip for or the tooltip is already open 29186 if ( !target.length || target.data( "ui-tooltip-id" ) ) { 29187 return; 29188 } 29189 29190 if ( target.attr( "title" ) ) { 29191 target.data( "ui-tooltip-title", target.attr( "title" ) ); 29192 } 29193 29194 target.data( "ui-tooltip-open", true ); 29195 29196 // Kill parent tooltips, custom or native, for hover 29197 if ( event && event.type === "mouseover" ) { 29198 target.parents().each( function() { 29199 var parent = $( this ), 29200 blurEvent; 29201 if ( parent.data( "ui-tooltip-open" ) ) { 29202 blurEvent = $.Event( "blur" ); 29203 blurEvent.target = blurEvent.currentTarget = this; 29204 that.close( blurEvent, true ); 29205 } 29206 if ( parent.attr( "title" ) ) { 29207 parent.uniqueId(); 29208 that.parents[ this.id ] = { 29209 element: this, 29210 title: parent.attr( "title" ) 29211 }; 29212 parent.attr( "title", "" ); 29213 } 29214 } ); 29215 } 29216 29217 this._registerCloseHandlers( event, target ); 29218 this._updateContent( target, event ); 29219 }, 29220 29221 _updateContent: function( target, event ) { 29222 var content, 29223 contentOption = this.options.content, 29224 that = this, 29225 eventType = event ? event.type : null; 29226 29227 if ( typeof contentOption === "string" || contentOption.nodeType || 29228 contentOption.jquery ) { 29229 return this._open( event, target, contentOption ); 29230 } 29231 29232 content = contentOption.call( target[ 0 ], function( response ) { 29233 29234 // Ignore async response if tooltip was closed already 29235 if ( !target.data( "ui-tooltip-open" ) ) { 29236 return; 29237 } 29238 29239 // JQuery creates a special event for focusin when it doesn't 29240 // exist natively. To improve performance, the native event 29241 // object is reused and the type is changed. Therefore, we can't 29242 // rely on the type being correct after the event finished 29243 // bubbling, so we set it back to the previous value. (#8740) 29244 if ( event ) { 29245 event.type = eventType; 29246 } 29247 that._open( event, target, response ); 29248 } ); 29249 if ( content ) { 29250 this._open( event, target, content ); 29251 } 29252 }, 29253 29254 _open: function( event, target, content ) { 29255 var tooltipData, tooltip, delayedShow, a11yContent, 29256 positionOption = $.extend( {}, this.options.position ); 29257 29258 if ( !content ) { 29259 return; 29260 } 29261 29262 // Content can be updated multiple times. If the tooltip already 29263 // exists, then just update the content and bail. 29264 tooltipData = this._find( target ); 29265 if ( tooltipData ) { 29266 tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content ); 29267 return; 29268 } 29269 29270 // If we have a title, clear it to prevent the native tooltip 29271 // we have to check first to avoid defining a title if none exists 29272 // (we don't want to cause an element to start matching [title]) 29273 // 29274 // We use removeAttr only for key events, to allow IE to export the correct 29275 // accessible attributes. For mouse events, set to empty string to avoid 29276 // native tooltip showing up (happens only when removing inside mouseover). 29277 if ( target.is( "[title]" ) ) { 29278 if ( event && event.type === "mouseover" ) { 29279 target.attr( "title", "" ); 29280 } else { 29281 target.removeAttr( "title" ); 29282 } 29283 } 29284 29285 tooltipData = this._tooltip( target ); 29286 tooltip = tooltipData.tooltip; 29287 this._addDescribedBy( target, tooltip.attr( "id" ) ); 29288 tooltip.find( ".ui-tooltip-content" ).html( content ); 29289 29290 // Support: Voiceover on OS X, JAWS on IE <= 9 29291 // JAWS announces deletions even when aria-relevant="additions" 29292 // Voiceover will sometimes re-read the entire log region's contents from the beginning 29293 this.liveRegion.children().hide(); 29294 a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() ); 29295 a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" ); 29296 a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" ); 29297 a11yContent.appendTo( this.liveRegion ); 29298 29299 function position( event ) { 29300 positionOption.of = event; 29301 if ( tooltip.is( ":hidden" ) ) { 29302 return; 29303 } 29304 tooltip.position( positionOption ); 29305 } 29306 if ( this.options.track && event && /^mouse/.test( event.type ) ) { 29307 this._on( this.document, { 29308 mousemove: position 29309 } ); 29310 29311 // trigger once to override element-relative positioning 29312 position( event ); 29313 } else { 29314 tooltip.position( $.extend( { 29315 of: target 29316 }, this.options.position ) ); 29317 } 29318 29319 tooltip.hide(); 29320 29321 this._show( tooltip, this.options.show ); 29322 29323 // Handle tracking tooltips that are shown with a delay (#8644). As soon 29324 // as the tooltip is visible, position the tooltip using the most recent 29325 // event. 29326 // Adds the check to add the timers only when both delay and track options are set (#14682) 29327 if ( this.options.track && this.options.show && this.options.show.delay ) { 29328 delayedShow = this.delayedShow = setInterval( function() { 29329 if ( tooltip.is( ":visible" ) ) { 29330 position( positionOption.of ); 29331 clearInterval( delayedShow ); 29332 } 29333 }, 13 ); 29334 } 29335 29336 this._trigger( "open", event, { tooltip: tooltip } ); 29337 }, 29338 29339 _registerCloseHandlers: function( event, target ) { 29340 var events = { 29341 keyup: function( event ) { 29342 if ( event.keyCode === $.ui.keyCode.ESCAPE ) { 29343 var fakeEvent = $.Event( event ); 29344 fakeEvent.currentTarget = target[ 0 ]; 29345 this.close( fakeEvent, true ); 29346 } 29347 } 29348 }; 29349 29350 // Only bind remove handler for delegated targets. Non-delegated 29351 // tooltips will handle this in destroy. 29352 if ( target[ 0 ] !== this.element[ 0 ] ) { 29353 events.remove = function() { 29354 var targetElement = this._find( target ); 29355 if ( targetElement ) { 29356 this._removeTooltip( targetElement.tooltip ); 29357 } 29358 }; 29359 } 29360 29361 if ( !event || event.type === "mouseover" ) { 29362 events.mouseleave = "close"; 29363 } 29364 if ( !event || event.type === "focusin" ) { 29365 events.focusout = "close"; 29366 } 29367 this._on( true, target, events ); 29368 }, 29369 29370 close: function( event ) { 29371 var tooltip, 29372 that = this, 29373 target = $( event ? event.currentTarget : this.element ), 29374 tooltipData = this._find( target ); 29375 29376 // The tooltip may already be closed 29377 if ( !tooltipData ) { 29378
29379 // We set ui-tooltip-open immediately upon open (in open()), but only set the 29380 // additional data once there's actually content to show (in _open()). So even if the 29381 // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in 29382 // the period between open() and _open(). 29383 target.removeData( "ui-tooltip-open" ); 29384 return; 29385 } 29386 29387 tooltip = tooltipData.tooltip; 29388 29389 // Disabling closes the tooltip, so we need to track when we're closing 29390 // to avoid an infinite loop in case the tooltip becomes disabled on close 29391 if ( tooltipData.closing ) { 29392 return; 29393 } 29394 29395 // Clear the interval for delayed tracking tooltips 29396 clearInterval( this.delayedShow ); 29397 29398 // Only set title if we had one before (see comment in _open()) 29399 // If the title attribute has changed since open(), don't restore 29400 if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) { 29401 target.attr( "title", target.data( "ui-tooltip-title" ) ); 29402 } 29403 29404 this._removeDescribedBy( target ); 29405 29406 tooltipData.hiding = true; 29407 tooltip.stop( true ); 29408 this._hide( tooltip, this.options.hide, function() { 29409 that._removeTooltip( $( this ) ); 29410 } ); 29411 29412 target.removeData( "ui-tooltip-open" ); 29413 this._off( target, "mouseleave focusout keyup" ); 29414 29415 // Remove 'remove' binding only on delegated targets 29416 if ( target[ 0 ] !== this.element[ 0 ] ) { 29417 this._off( target, "remove" ); 29418 } 29419 this._off( this.document, "mousemove" ); 29420 29421 if ( event && event.type === "mouseleave" ) { 29422 $.each( this.parents, function( id, parent ) { 29423 $( parent.element ).attr( "title", parent.title ); 29424 delete that.parents[ id ]; 29425 } ); 29426 } 29427 29428 tooltipData.closing = true; 29429 this._trigger( "close", event, { tooltip: tooltip } ); 29430 if ( !tooltipData.hiding ) { 29431 tooltipData.closing = false; 29432 } 29433 }, 29434 29435 _tooltip: function( element ) { 29436 var tooltip = $( "<div>" ).attr( "role", "tooltip" ), 29437 content = $( "<div>" ).appendTo( tooltip ), 29438 id = tooltip.uniqueId().attr( "id" ); 29439 29440 this._addClass( content, "ui-tooltip-content" ); 29441 this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" ); 29442 29443 tooltip.appendTo( this._appendTo( element ) ); 29444 29445 return this.tooltips[ id ] = { 29446 element: element, 29447 tooltip: tooltip 29448 }; 29449 }, 29450 29451 _find: function( target ) { 29452 var id = target.data( "ui-tooltip-id" ); 29453 return id ? this.tooltips[ id ] : null; 29454 }, 29455 29456 _removeTooltip: function( tooltip ) { 29457 29458 // Clear the interval for delayed tracking tooltips 29459 clearInterval( this.delayedShow ); 29460 29461 tooltip.remove(); 29462 delete this.tooltips[ tooltip.attr( "id" ) ]; 29463 }, 29464 29465 _appendTo: function( target ) { 29466 var element = target.closest( ".ui-front, dialog" ); 29467 29468 if ( !element.length ) { 29469 element = this.document[ 0 ].body; 29470 } 29471 29472 return element; 29473 }, 29474 29475 _destroy: function() { 29476 var that = this; 29477 29478 // Close open tooltips 29479 $.each( this.tooltips, function( id, tooltipData ) { 29480 29481 // Delegate to close method to handle common cleanup 29482 var event = $.Event( "blur" ), 29483 element = tooltipData.element; 29484 event.target = event.currentTarget = element[ 0 ]; 29485 that.close( event, true ); 29486 29487 // Remove immediately; destroying an open tooltip doesn't use the 29488 // hide animation 29489 $( "#" + id ).remove(); 29490 29491 // Restore the title 29492 if ( element.data( "ui-tooltip-title" ) ) { 29493 29494 // If the title attribute has changed since open(), don't restore 29495 if ( !element.attr( "title" ) ) { 29496 element.attr( "title", element.data( "ui-tooltip-title" ) ); 29497 } 29498 element.removeData( "ui-tooltip-title" ); 29499 } 29500 } ); 29501 this.liveRegion.remove(); 29502 } 29503} ); 29504 29505// DEPRECATED 29506// TODO: Switch return back to widget declaration at top of file when this is removed 29507if ( $.uiBackCompat === true ) { 29508 29509 // Backcompat for tooltipClass option 29510 $.widget( "ui.tooltip", $.ui.tooltip, { 29511 options: { 29512 tooltipClass: null 29513 }, 29514 _tooltip: function() { 29515 var tooltipData = this._superApply( arguments ); 29516 if ( this.options.tooltipClass ) { 29517 tooltipData.tooltip.addClass( this.options.tooltipClass ); 29518 } 29519 return tooltipData; 29520 } 29521 } ); 29522} 29523 29524var widgetsTooltip = $.ui.tooltip; 29525 29526 29527 29528 29529} );; 29530/*! 29531 * jQuery Migrate - v3.0.1 - 2017-09-26 29532 * Copyright jQuery Foundation and other contributors 29533 */ 29534;( function( factory ) { 29535 if ( typeof define === "function" && define.amd ) { 29536 29537 // AMD. Register as an anonymous module. 29538 define( [ "jquery" ], window, factory ); 29539 } else if ( typeof module === "object" && module.exports ) { 29540 29541 // Node/CommonJS 29542 // eslint-disable-next-line no-undef 29543 module.exports = factory( require( "jquery" ), window ); 29544 } else { 29545 29546 // Browser globals 29547 factory( jQuery, window ); 29548 } 29549} )( function( jQuery, window ) { 29550"use strict"; 29551 29552 29553jQuery.migrateVersion = "3.0.1"; 29554 29555/* exported migrateWarn, migrateWarnFunc, migrateWarnProp */ 29556 29557( function() { 29558 29559 var rbadVersions = /^[12]\./; 29560 29561 // Support: IE9 only 29562 // IE9 only creates console object when dev tools are first opened 29563 // IE9 console is a host object, callable but doesn't have .apply() 29564 if ( !window.console || !window.console.log ) { 29565 return; 29566 } 29567 29568 // Need jQuery 3.0.0+ and no older Migrate loaded 29569 if ( !jQuery || rbadVersions.test( jQuery.fn.jquery ) ) { 29570 window.console.log( "JQMIGRATE: jQuery 3.0.0+ REQUIRED" ); 29571 } 29572 if ( jQuery.migrateWarnings ) { 29573 window.console.log( "JQMIGRATE: Migrate plugin loaded multiple times" ); 29574 } 29575 29576 // Show a message on the console so devs know we're active 29577 window.console.log( "JQMIGRATE: Migrate is installed" + 29578 ( jQuery.migrateMute ? "" : " with logging active" ) + 29579 ", version " + jQuery.migrateVersion ); 29580 29581} )(); 29582 29583var warnedAbout = {}; 29584 29585// List of warnings already given; public read only 29586jQuery.migrateWarnings = []; 29587 29588// Set to false to disable traces that appear with warnings 29589if ( jQuery.migrateTrace === undefined ) { 29590 jQuery.migrateTrace = true; 29591} 29592 29593// Forget any warnings we've already given; public 29594jQuery.migrateReset = function() { 29595 warnedAbout = {}; 29596 jQuery.migrateWarnings.length = 0; 29597}; 29598 29599function migrateWarn( msg ) { 29600 var console = window.console; 29601 if ( !warnedAbout[ msg ] ) { 29602 warnedAbout[ msg ] = true; 29603 jQuery.migrateWarnings.push( msg ); 29604 if ( console && console.warn && !jQuery.migrateMute ) { 29605 console.warn( "JQMIGRATE: " + msg ); 29606 if ( jQuery.migrateTrace && console.trace ) { 29607 console.trace(); 29608 } 29609 } 29610 } 29611} 29612 29613function migrateWarnProp( obj, prop, value, msg ) { 29614 Object.defineProperty( obj, prop, { 29615 configurable: true, 29616 enumerable: true, 29617 get: function() { 29618 migrateWarn( msg ); 29619 return value; 29620 }, 29621 set: function( newValue ) { 29622 migrateWarn( msg ); 29623 value = newValue; 29624 } 29625 } ); 29626} 29627 29628function migrateWarnFunc( obj, prop, newFunc, msg ) { 29629 obj[ prop ] = function() { 29630 migrateWarn( msg ); 29631 return newFunc.apply( this, arguments ); 29632 }; 29633} 29634 29635if ( window.document.compatMode === "BackCompat" ) { 29636 29637 // JQuery has never supported or tested Quirks Mode 29638 migrateWarn( "jQuery is not compatible with Quirks Mode" ); 29639} 29640 29641 29642var oldInit = jQuery.fn.init, 29643 oldIsNumeric = jQuery.isNumeric, 29644 oldFind = jQuery.find, 29645 rattrHashTest = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/, 29646 rattrHashGlob = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g; 29647 29648jQuery.fn.init = function( arg1 ) { 29649 var args = Array.prototype.slice.call( arguments ); 29650 29651 if ( typeof arg1 === "string" && arg1 === "#" ) { 29652 29653 // JQuery( "#" ) is a bogus ID selector, but it returned an empty set before jQuery 3.0 29654 migrateWarn( "jQuery( '#' ) is not a valid selector" ); 29655 args[ 0 ] = []; 29656 } 29657 29658 return oldInit.apply( this, args ); 29659};
29660jQuery.fn.init.prototype = jQuery.fn; 29661 29662jQuery.find = function( selector ) { 29663 var args = Array.prototype.slice.call( arguments ); 29664 29665 // Support: PhantomJS 1.x 29666 // String#match fails to match when used with a //g RegExp, only on some strings 29667 if ( typeof selector === "string" && rattrHashTest.test( selector ) ) { 29668 29669 // The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0 29670 // First see if qS thinks it's a valid selector, if so avoid a false positive 29671 try { 29672 window.document.querySelector( selector ); 29673 } catch ( err1 ) { 29674 29675 // Didn't *look* valid to qSA, warn and try quoting what we think is the value 29676 selector = selector.replace( rattrHashGlob, function( _, attr, op, value ) { 29677 return "[" + attr + op + "\"" + value + "\"]"; 29678 } ); 29679 29680 // If the regexp *may* have created an invalid selector, don't update it 29681 // Note that there may be false alarms if selector uses jQuery extensions 29682 try { 29683 window.document.querySelector( selector ); 29684 migrateWarn( "Attribute selector with '#' must be quoted: " + args[ 0 ] ); 29685 args[ 0 ] = selector; 29686 } catch ( err2 ) { 29687 migrateWarn( "Attribute selector with '#' was not fixed: " + args[ 0 ] ); 29688 } 29689 } 29690 } 29691 29692 return oldFind.apply( this, args ); 29693}; 29694 29695// Copy properties attached to original jQuery.find method (e.g. .attr, .isXML) 29696var findProp; 29697for ( findProp in oldFind ) { 29698 if ( Object.prototype.hasOwnProperty.call( oldFind, findProp ) ) { 29699 jQuery.find[ findProp ] = oldFind[ findProp ]; 29700 } 29701} 29702 29703// The number of elements contained in the matched element set 29704jQuery.fn.size = function() { 29705 migrateWarn( "jQuery.fn.size() is deprecated and removed; use the .length property" ); 29706 return this.length; 29707}; 29708 29709jQuery.parseJSON = function() { 29710 migrateWarn( "jQuery.parseJSON is deprecated; use JSON.parse" ); 29711 return JSON.parse.apply( null, arguments ); 29712}; 29713 29714jQuery.isNumeric = function( val ) { 29715 29716 // The jQuery 2.2.3 implementation of isNumeric 29717 function isNumeric2( obj ) { 29718 var realStringObj = obj && obj.toString(); 29719 return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0; 29720 } 29721 29722 var newValue = oldIsNumeric( val ), 29723 oldValue = isNumeric2( val ); 29724 29725 if ( newValue !== oldValue ) { 29726 migrateWarn( "jQuery.isNumeric() should not be called on constructed objects" ); 29727 } 29728 29729 return oldValue; 29730}; 29731 29732migrateWarnFunc( jQuery, "holdReady", jQuery.holdReady, 29733 "jQuery.holdReady is deprecated" ); 29734 29735migrateWarnFunc( jQuery, "unique", jQuery.uniqueSort, 29736 "jQuery.unique is deprecated; use jQuery.uniqueSort" ); 29737 29738// Now jQuery.expr.pseudos is the standard incantation 29739migrateWarnProp( jQuery.expr, "filters", jQuery.expr.pseudos, 29740 "jQuery.expr.filters is deprecated; use jQuery.expr.pseudos" ); 29741migrateWarnProp( jQuery.expr, ":", jQuery.expr.pseudos, 29742 "jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos" ); 29743 29744 29745var oldAjax = jQuery.ajax; 29746 29747jQuery.ajax = function( ) { 29748 var jQXHR = oldAjax.apply( this, arguments ); 29749 29750 // Be sure we got a jQXHR (e.g., not sync) 29751 if ( jQXHR.promise ) { 29752 migrateWarnFunc( jQXHR, "success", jQXHR.done, 29753 "jQXHR.success is deprecated and removed" ); 29754 migrateWarnFunc( jQXHR, "error", jQXHR.fail, 29755 "jQXHR.error is deprecated and removed" ); 29756 migrateWarnFunc( jQXHR, "complete", jQXHR.always, 29757 "jQXHR.complete is deprecated and removed" ); 29758 } 29759 29760 return jQXHR; 29761}; 29762 29763 29764var oldRemoveAttr = jQuery.fn.removeAttr, 29765 oldToggleClass = jQuery.fn.toggleClass, 29766 rmatchNonSpace = /\S+/g; 29767 29768jQuery.fn.removeAttr = function( name ) { 29769 var self = this; 29770 29771 jQuery.each( name.match( rmatchNonSpace ), function( i, attr ) { 29772 if ( jQuery.expr.match.bool.test( attr ) ) { 29773 migrateWarn( "jQuery.fn.removeAttr no longer sets boolean properties: " + attr ); 29774 self.prop( attr, false ); 29775 } 29776 } ); 29777 29778 return oldRemoveAttr.apply( this, arguments ); 29779}; 29780 29781jQuery.fn.toggleClass = function( state ) { 29782 29783 // Only deprecating no-args or single boolean arg 29784 if ( state !== undefined && typeof state !== "boolean" ) { 29785 return oldToggleClass.apply( this, arguments ); 29786 } 29787 29788 migrateWarn( "jQuery.fn.toggleClass( boolean ) is deprecated" ); 29789 29790 // Toggle entire class name of each element 29791 return this.each( function() { 29792 var className = this.getAttribute && this.getAttribute( "class" ) || ""; 29793 29794 if ( className ) { 29795 jQuery.data( this, "__className__", className ); 29796 } 29797 29798 // If the element has a class name or if we're passed `false`, 29799 // then remove the whole classname (if there was one, the above saved it). 29800 // Otherwise bring back whatever was previously saved (if anything), 29801 // falling back to the empty string if nothing was stored. 29802 if ( this.setAttribute ) { 29803 this.setAttribute( "class", 29804 className || state === false ? 29805 "" : 29806 jQuery.data( this, "__className__" ) || "" 29807 ); 29808 } 29809 } ); 29810};
29811 29812 29813var internalSwapCall = false; 29814 29815// If this version of jQuery has .swap(), don't false-alarm on internal uses 29816if ( jQuery.swap ) { 29817 jQuery.each( [ "height", "width", "reliableMarginRight" ], function( _, name ) { 29818 var oldHook = jQuery.cssHooks[ name ] && jQuery.cssHooks[ name ].get; 29819 29820 if ( oldHook ) { 29821 jQuery.cssHooks[ name ].get = function() { 29822 var ret; 29823 29824 internalSwapCall = true; 29825 ret = oldHook.apply( this, arguments ); 29826 internalSwapCall = false; 29827 return ret; 29828 }; 29829 } 29830 } ); 29831} 29832 29833jQuery.swap = function( elem, options, callback, args ) { 29834 var ret, name, 29835 old = {}; 29836 29837 if ( !internalSwapCall ) { 29838 migrateWarn( "jQuery.swap() is undocumented and deprecated" ); 29839 } 29840 29841 // Remember the old values, and insert the new ones 29842 for ( name in options ) { 29843 old[ name ] = elem.style[ name ]; 29844 elem.style[ name ] = options[ name ]; 29845 } 29846 29847 ret = callback.apply( elem, args || [] ); 29848 29849 // Revert the old values 29850 for ( name in options ) { 29851 elem.style[ name ] = old[ name ]; 29852 } 29853 29854 return ret; 29855}; 29856 29857var oldData = jQuery.data; 29858 29859jQuery.data = function( elem, name, value ) { 29860 var curData; 29861 29862 // Name can be an object, and each entry in the object is meant to be set as data 29863 if ( name && typeof name === "object" && arguments.length === 2 ) { 29864 curData = jQuery.hasData( elem ) && oldData.call( this, elem ); 29865 var sameKeys = {}; 29866 for ( var key in name ) { 29867 if ( key !== jQuery.camelCase( key ) ) { 29868 migrateWarn( "jQuery.data() always sets/gets camelCased names: " + key ); 29869 curData[ key ] = name[ key ]; 29870 } else { 29871 sameKeys[ key ] = name[ key ]; 29872 } 29873 } 29874 29875 oldData.call( this, elem, sameKeys ); 29876 29877 return name; 29878 } 29879 29880 // If the name is transformed, look for the un-transformed name in the data object 29881 if ( name && typeof name === "string" && name !== jQuery.camelCase( name ) ) { 29882 curData = jQuery.hasData( elem ) && oldData.call( this, elem ); 29883 if ( curData && name in curData ) { 29884 migrateWarn( "jQuery.data() always sets/gets camelCased names: " + name ); 29885 if ( arguments.length > 2 ) { 29886 curData[ name ] = value; 29887 } 29888 return curData[ name ]; 29889 } 29890 } 29891 29892 return oldData.apply( this, arguments ); 29893}; 29894 29895var oldTweenRun = jQuery.Tween.prototype.run; 29896var linearEasing = function( pct ) { 29897 return pct; 29898 }; 29899 29900jQuery.Tween.prototype.run = function( ) { 29901 if ( jQuery.easing[ this.easing ].length > 1 ) { 29902 migrateWarn( 29903 "'jQuery.easing." + this.easing.toString() + "' should use only one argument" 29904 ); 29905 29906 jQuery.easing[ this.easing ] = linearEasing; 29907 } 29908 29909 oldTweenRun.apply( this, arguments ); 29910}; 29911 29912jQuery.fx.interval = jQuery.fx.interval || 13; 29913 29914// Support: IE9, Android <=4.4 29915// Avoid false positives on browsers that lack rAF 29916if ( window.requestAnimationFrame ) { 29917 migrateWarnProp( jQuery.fx, "interval", jQuery.fx.interval, 29918 "jQuery.fx.interval is deprecated" ); 29919} 29920 29921var oldLoad = jQuery.fn.load, 29922 oldEventAdd = jQuery.event.add, 29923 originalFix = jQuery.event.fix; 29924 29925jQuery.event.props = []; 29926jQuery.event.fixHooks = {}; 29927 29928migrateWarnProp( jQuery.event.props, "concat", jQuery.event.props.concat, 29929 "jQuery.event.props.concat() is deprecated and removed" ); 29930 29931jQuery.event.fix = function( originalEvent ) { 29932 var event, 29933 type = originalEvent.type, 29934 fixHook = this.fixHooks[ type ], 29935 props = jQuery.event.props; 29936 29937 if ( props.length ) { 29938 migrateWarn( "jQuery.event.props are deprecated and removed: " + props.join() ); 29939 while ( props.length ) { 29940 jQuery.event.addProp( props.pop() ); 29941 } 29942 } 29943 29944 if ( fixHook && !fixHook._migrated_ ) { 29945 fixHook._migrated_ = true; 29946 migrateWarn( "jQuery.event.fixHooks are deprecated and removed: " + type ); 29947 if ( ( props = fixHook.props ) && props.length ) { 29948 while ( props.length ) { 29949 jQuery.event.addProp( props.pop() ); 29950 } 29951 } 29952 } 29953 29954 event = originalFix.call( this, originalEvent ); 29955 29956 return fixHook && fixHook.filter ? fixHook.filter( event, originalEvent ) : event; 29957}; 29958 29959jQuery.event.add = function( elem, types ) { 29960 29961 // This misses the multiple-types case but that seems awfully rare 29962 if ( elem === window && types === "load" && window.document.readyState === "complete" ) { 29963 migrateWarn( "jQuery(window).on('load'...) called after load event occurred" ); 29964 } 29965 return oldEventAdd.apply( this, arguments ); 29966};
29967 29968jQuery.each( [ "load", "unload", "error" ], function( _, name ) { 29969 29970 jQuery.fn[ name ] = function() { 29971 var args = Array.prototype.slice.call( arguments, 0 ); 29972 29973 // If this is an ajax load() the first arg should be the string URL; 29974 // technically this could also be the "Anything" arg of the event .load() 29975 // which just goes to show why this dumb signature has been deprecated! 29976 // jQuery custom builds that exclude the Ajax module justifiably die here. 29977 if ( name === "load" && typeof args[ 0 ] === "string" ) { 29978 return oldLoad.apply( this, args ); 29979 } 29980 29981 migrateWarn( "jQuery.fn." + name + "() is deprecated" ); 29982 29983 args.splice( 0, 0, name ); 29984 if ( arguments.length ) { 29985 return this.on.apply( this, args ); 29986 } 29987 29988 // Use .triggerHandler here because: 29989 // - load and unload events don't need to bubble, only applied to window or image 29990 // - error event should not bubble to window, although it does pre-1.7 29991 // See http://bugs.jquery.com/ticket/11820 29992 this.triggerHandler.apply( this, args ); 29993 return this; 29994 }; 29995 29996} ); 29997 29998jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + 29999 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + 30000 "change select submit keydown keypress keyup contextmenu" ).split( " " ), 30001 function( i, name ) { 30002 30003 // Handle event binding 30004 jQuery.fn[ name ] = function( data, fn ) { 30005 migrateWarn( "jQuery.fn." + name + "() event shorthand is deprecated" ); 30006 return arguments.length > 0 ? 30007 this.on( name, null, data, fn ) : 30008 this.trigger( name ); 30009 }; 30010} ); 30011 30012// Trigger "ready" event only once, on document ready 30013jQuery( function() { 30014 jQuery( window.document ).triggerHandler( "ready" ); 30015} ); 30016 30017jQuery.event.special.ready = { 30018 setup: function() { 30019 if ( this === window.document ) { 30020 migrateWarn( "'ready' event is deprecated" ); 30021 } 30022 } 30023}; 30024 30025jQuery.fn.extend( { 30026 30027 bind: function( types, data, fn ) { 30028 migrateWarn( "jQuery.fn.bind() is deprecated" ); 30029 return this.on( types, null, data, fn ); 30030 }, 30031 unbind: function( types, fn ) { 30032 migrateWarn( "jQuery.fn.unbind() is deprecated" ); 30033 return this.off( types, null, fn ); 30034 }, 30035 delegate: function( selector, types, data, fn ) { 30036 migrateWarn( "jQuery.fn.delegate() is deprecated" ); 30037 return this.on( types, selector, data, fn ); 30038 }, 30039 undelegate: function( selector, types, fn ) { 30040 migrateWarn( "jQuery.fn.undelegate() is deprecated" ); 30041 return arguments.length === 1 ? 30042 this.off( selector, "**" ) : 30043 this.off( types, selector || "**", fn ); 30044 }, 30045 hover: function( fnOver, fnOut ) { 30046 migrateWarn( "jQuery.fn.hover() is deprecated" ); 30047 return this.on( "mouseenter", fnOver ).on( "mouseleave", fnOut || fnOver ); 30048 } 30049} ); 30050 30051 30052var oldOffset = jQuery.fn.offset; 30053 30054jQuery.fn.offset = function() { 30055 var docElem, 30056 elem = this[ 0 ], 30057 origin = { top: 0, left: 0 }; 30058 30059 if ( !elem || !elem.nodeType ) { 30060 migrateWarn( "jQuery.fn.offset() requires a valid DOM element" ); 30061 return origin; 30062 } 30063 30064 docElem = ( elem.ownerDocument || window.document ).documentElement; 30065 if ( !jQuery.contains( docElem, elem ) ) { 30066 migrateWarn( "jQuery.fn.offset() requires an element connected to a document" ); 30067 return origin; 30068 } 30069 30070 return oldOffset.apply( this, arguments ); 30071}; 30072 30073 30074var oldParam = jQuery.param; 30075 30076jQuery.param = function( data, traditional ) { 30077 var ajaxTraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; 30078 30079 if ( traditional === undefined && ajaxTraditional ) { 30080 30081 migrateWarn( "jQuery.param() no longer uses jQuery.ajaxSettings.traditional" ); 30082 traditional = ajaxTraditional; 30083 } 30084 30085 return oldParam.call( this, data, traditional ); 30086}; 30087 30088var oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack; 30089 30090jQuery.fn.andSelf = function() { 30091 migrateWarn( "jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()" ); 30092 return oldSelf.apply( this, arguments ); 30093}; 30094 30095 30096var oldDeferred = jQuery.Deferred, 30097 tuples = [ 30098 30099 // Action, add listener, callbacks, .then handlers, final state 30100 [ "resolve", "done", jQuery.Callbacks( "once memory" ), 30101 jQuery.Callbacks( "once memory" ), "resolved" ], 30102 [ "reject", "fail", jQuery.Callbacks( "once memory" ), 30103 jQuery.Callbacks( "once memory" ), "rejected" ], 30104 [ "notify", "progress", jQuery.Callbacks( "memory" ), 30105 jQuery.Callbacks( "memory" ) ] 30106 ]; 30107 30108jQuery.Deferred = function( func ) { 30109 var deferred = oldDeferred(), 30110 promise = deferred.promise(); 30111 30112 deferred.pipe = promise.pipe = function( /* fnDone, fnFail, fnProgress */ ) { 30113 var fns = arguments; 30114 30115 migrateWarn( "deferred.pipe() is deprecated" ); 30116 30117 return jQuery.Deferred( function( newDefer ) { 30118 jQuery.each( tuples, function( i, tuple ) { 30119 var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; 30120 30121 // Deferred.done(function() { bind to newDefer or newDefer.resolve }) 30122 // deferred.fail(function() { bind to newDefer or newDefer.reject }) 30123 // deferred.progress(function() { bind to newDefer or newDefer.notify }) 30124 deferred[ tuple[ 1 ] ]( function() { 30125 var returned = fn && fn.apply( this, arguments ); 30126 if ( returned && jQuery.isFunction( returned.promise ) ) { 30127 returned.promise() 30128 .done( newDefer.resolve ) 30129 .fail( newDefer.reject ) 30130 .progress( newDefer.notify ); 30131 } else { 30132 newDefer[ tuple[ 0 ] + "With" ]( 30133 this === promise ? newDefer.promise() : this, 30134 fn ? [ returned ] : arguments 30135 ); 30136 } 30137 } ); 30138 } ); 30139 fns = null; 30140 } ).promise(); 30141 30142 }; 30143 30144 if ( func ) { 30145 func.call( deferred, deferred ); 30146 } 30147 30148 return deferred; 30149}; 30150 30151// Preserve handler of uncaught exceptions in promise chains 30152jQuery.Deferred.exceptionHook = oldDeferred.exceptionHook; 30153 30154return jQuery; 30155} ); 30156; 30157/*! 30158 * Modernizr v2.8.3 30159 * www.modernizr.com 30160 * 30161 * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton 30162 * Available under the BSD and MIT licenses: www.modernizr.com/license/ 30163 */ 30164 30165/* 30166 * Modernizr tests which native CSS3 and HTML5 features are available in 30167 * the current UA and makes the results available to you in two ways: 30168 * as properties on a global Modernizr object, and as classes on the 30169 * <html> element. This information allows you to progressively enhance 30170 * your pages with a granular level of control over the experience. 30171 * 30172 * Modernizr has an optional (not included) conditional resource loader 30173 * called Modernizr.load(), based on Yepnope.js (yepnopejs.com). 30174 * To get a build that includes Modernizr.load(), as well as choosing 30175 * which tests to include, go to www.modernizr.com/download/ 30176 * 30177 * Authors Faruk Ates, Paul Irish, Alex Sexton 30178 * Contributors Ryan Seddon, Ben Alman 30179 */ 30180 30181window.Modernizr = (function( window, document, undefined ) { 30182 30183 var version = '2.8.3', 30184 30185 Modernizr = {}, 30186 30187 /*>>cssclasses*/ 30188 // option for enabling the HTML classes to be added 30189 enableClasses = true, 30190 /*>>cssclasses*/ 30191 30192 docElement = document.documentElement, 30193 30194 /** 30195 * Create our "modernizr" element that we do most feature tests on. 30196 */ 30197 mod = 'modernizr', 30198 modElem = document.createElement(mod), 30199 mStyle = modElem.style, 30200 30201 /** 30202 * Create the input element for various Web Forms feature tests. 30203 */ 30204 inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ , 30205 30206 /*>>smile*/ 30207 smile = ':)', 30208 /*>>smile*/ 30209 30210 toString = {}.toString, 30211 30212 // TODO :: make the prefixes more granular 30213 /*>>prefixes*/ 30214 // List of property values to set for css tests. See ticket #21 30215 prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), 30216 /*>>prefixes*/ 30217 30218 /*>>domprefixes*/ 30219 // Following spec is to expose vendor-specific style properties as: 30220 // elem.style.WebkitBorderRadius 30221 // and the following would be incorrect: 30222 // elem.style.webkitBorderRadius 30223 30224 // Webkit ghosts their properties in lowercase but Opera & Moz do not. 30225 // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+ 30226 // erik.eae.net/archives/2008/03/10/21.48.10/ 30227 30228 // More here: github.com/Modernizr/Modernizr/issues/issue/21 30229 omPrefixes = 'Webkit Moz O ms', 30230 30231 cssomPrefixes = omPrefixes.split(' '), 30232 30233 domPrefixes = omPrefixes.toLowerCase().split(' '), 30234 /*>>domprefixes*/ 30235 30236 /*>>ns*/ 30237 ns = {'svg': 'http://www.w3.org/2000/svg'}, 30238 /*>>ns*/ 30239 30240 tests = {}, 30241 inputs = {}, 30242 attrs = {}, 30243 30244 classes = [], 30245 30246 slice = classes.slice, 30247 30248 featureName, // used in testing loop 30249 30250 30251 /*>>
vendor: 21,759 bytes, lines 30251-30860
30251teststyles*/ 30252 // Inject element with style element and some CSS rules 30253 injectElementWithStyles = function( rule, callback, nodes, testnames ) { 30254 30255 var style, ret, node, docOverflow, 30256 div = document.createElement('div'), 30257 // After page load injecting a fake body doesn't work so check if body exists 30258 body = document.body, 30259 // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it. 30260 fakeBody = body || document.createElement('body'); 30261 30262 if ( parseInt(nodes, 10) ) { 30263 // In order not to give false positives we create a node for each test 30264 // This also allows the method to scale for unspecified uses 30265 while ( nodes-- ) { 30266 node = document.createElement('div'); 30267 node.id = testnames ? testnames[nodes] : mod + (nodes + 1); 30268 div.appendChild(node); 30269 } 30270 } 30271 30272 // <style> elements in IE6-9 are considered 'NoScope' elements and therefore will be removed 30273 // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element 30274 // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements. 30275 // msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx 30276 // Documents served as xml will throw if using ­ so use xml friendly encoded version. See issue #277 30277 style = ['­','<style id="s', mod, '">', rule, '</style>'].join(''); 30278 div.id = mod; 30279 // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody. 30280 // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 30281 (body ? div : fakeBody).innerHTML += style; 30282 fakeBody.appendChild(div); 30283 if ( !body ) { 30284 //avoid crashing IE8, if background image is used 30285 fakeBody.style.background = ''; 30286 //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible 30287 fakeBody.style.overflow = 'hidden'; 30288 docOverflow = docElement.style.overflow; 30289 docElement.style.overflow = 'hidden'; 30290 docElement.appendChild(fakeBody); 30291 } 30292 30293 ret = callback(div, rule); 30294 // If this is done after page load we don't want to remove the body so check if body exists 30295 if ( !body ) { 30296 fakeBody.parentNode.removeChild(fakeBody); 30297 docElement.style.overflow = docOverflow; 30298 } else { 30299 div.parentNode.removeChild(div); 30300 } 30301 30302 return !!ret; 30303 30304 }, 30305 /*>>teststyles*/ 30306 30307 /*>>mq*/ 30308 // adapted from matchMedia polyfill 30309 // by Scott Jehl and Paul Irish 30310 // gist.github.com/786768 30311 testMediaQuery = function( mq ) { 30312 30313 var matchMedia = window.matchMedia || window.msMatchMedia; 30314 if ( matchMedia ) { 30315 return matchMedia(mq) && matchMedia(mq).matches || false; 30316 } 30317 30318 var bool; 30319 30320 injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) { 30321 bool = (window.getComputedStyle ? 30322 getComputedStyle(node, null) : 30323 node.currentStyle)['position'] == 'absolute'; 30324 }); 30325 30326 return bool; 30327 30328 }, 30329 /*>>mq*/ 30330 30331 30332 /*>>hasevent*/ 30333 // 30334 // isEventSupported determines if a given element supports the given event 30335 // kangax.github.com/iseventsupported/ 30336 // 30337 // The following results are known incorrects: 30338 // Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative 30339 // Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333 30340 // ... 30341 isEventSupported = (function() { 30342 30343 var TAGNAMES = { 30344 'select': 'input', 'change': 'input', 30345 'submit': 'form', 'reset': 'form', 30346 'error': 'img', 'load': 'img', 'abort': 'img' 30347 }; 30348 30349 function isEventSupported( eventName, element ) { 30350 30351 element = element || document.createElement(TAGNAMES[eventName] || 'div'); 30352 eventName = 'on' + eventName; 30353 30354 // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those 30355 var isSupported = eventName in element; 30356 30357 if ( !isSupported ) { 30358 // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element 30359 if ( !element.setAttribute ) { 30360 element = document.createElement('div'); 30361 } 30362 if ( element.setAttribute && element.removeAttribute ) { 30363 element.setAttribute(eventName, ''); 30364 isSupported = is(element[eventName], 'function'); 30365 30366 // If property was created, "remove it" (by setting value to `undefined`) 30367 if ( !is(element[eventName], 'undefined') ) { 30368 element[eventName] = undefined; 30369 } 30370 element.removeAttribute(eventName); 30371 } 30372 } 30373 30374 element = null; 30375 return isSupported; 30376 } 30377 return isEventSupported; 30378 })(), 30379 /*>>hasevent*/ 30380 30381 // TODO :: Add flag for hasownprop ? didn't last time 30382 30383 // hasOwnProperty shim by kangax needed for Safari 2.0 support 30384 _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; 30385 30386 if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { 30387 hasOwnProp = function (object, property) { 30388 return _hasOwnProperty.call(object, property); 30389 }; 30390 } 30391 else { 30392 hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ 30393 return ((property in object) && is(object.constructor.prototype[property], 'undefined')); 30394 }; 30395 } 30396 30397 // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js 30398 // es5.github.com/#x15.3.4.5 30399 30400 if (!Function.prototype.bind) { 30401 Function.prototype.bind = function bind(that) { 30402 30403 var target = this; 30404 30405 if (typeof target != "function") { 30406 throw new TypeError(); 30407 } 30408 30409 var args = slice.call(arguments, 1), 30410 bound = function () { 30411 30412 if (this instanceof bound) { 30413 30414 var F = function(){}; 30415 F.prototype = target.prototype; 30416 var self = new F(); 30417 30418 var result = target.apply( 30419 self, 30420 args.concat(slice.call(arguments)) 30421 ); 30422 if (Object(result) === result) { 30423 return result; 30424 } 30425 return self; 30426 30427 } else { 30428 30429 return target.apply( 30430 that, 30431 args.concat(slice.call(arguments)) 30432 ); 30433 30434 } 30435 30436 }; 30437 30438 return bound; 30439 }; 30440 } 30441 30442 /** 30443 * setCss applies given styles to the Modernizr DOM node. 30444 */ 30445 function setCss( str ) { 30446 mStyle.cssText = str; 30447 } 30448 30449 /** 30450 * setCssAll extrapolates all vendor-specific css strings. 30451 */ 30452 function setCssAll( str1, str2 ) { 30453 return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); 30454 } 30455 30456 /** 30457 * is returns a boolean for if typeof obj is exactly type. 30458 */ 30459 function is( obj, type ) { 30460 return typeof obj === type; 30461 } 30462 30463 /** 30464 * contains returns a boolean for if substr is found within str. 30465 */ 30466 function contains( str, substr ) { 30467 return !!~('' + str).indexOf(substr); 30468 } 30469 30470 /*>>testprop*/ 30471 30472 // testProps is a generic CSS / DOM property test. 30473 30474 // In testing support for a given CSS property, it's legit to test: 30475 // `elem.style[styleName] !== undefined` 30476 // If the property is supported it will return an empty string, 30477 // if unsupported it will return undefined. 30478 30479 // We'll take advantage of this quick test and skip setting a style 30480 // on our modernizr element, but instead just testing undefined vs 30481 // empty string. 30482 30483 // Because the testing of the CSS property names (with "-", as 30484 // opposed to the camelCase DOM properties) is non-portable and 30485 // non-standard but works in WebKit and IE (but not Gecko or Opera), 30486 // we explicitly reject properties with dashes so that authors 30487 // developing in WebKit or IE first don't end up with 30488 // browser-specific content by accident. 30489 30490 function testProps( props, prefixed ) { 30491 for ( var i in props ) { 30492 var prop = props[i]; 30493 if ( !contains(prop, "-") && mStyle[prop] !== undefined ) { 30494 return prefixed == 'pfx' ? prop : true; 30495 } 30496 } 30497 return false; 30498 } 30499 /*>>testprop*/ 30500 30501 // TODO :: add testDOMProps 30502 /** 30503 * testDOMProps is a generic DOM property test; if a browser supports 30504 * a certain property, it won't return undefined for it. 30505 */ 30506 function testDOMProps( props, obj, elem ) { 30507 for ( var i in props ) { 30508 var item = obj[props[i]]; 30509 if ( item !== undefined) { 30510 30511 // return the property name as a string 30512 if (elem === false) return props[i]; 30513 30514 // let's bind a function 30515 if (is(item, 'function')){ 30516 // default to autobind unless override 30517 return item.bind(elem || obj); 30518 } 30519 30520 // return the unbound function or obj or value 30521 return item; 30522 } 30523 } 30524 return false; 30525 } 30526 30527 /*>>testallprops*/ 30528 /** 30529 * testPropsAll tests a list of DOM properties we want to check against. 30530 * We specify literally ALL possible (known and/or likely) properties on 30531 * the element including the non-vendor prefixed one, for forward- 30532 * compatibility. 30533 */ 30534 function testPropsAll( prop, prefixed, elem ) { 30535 30536 var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), 30537 props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); 30538 30539 // did they call .prefixed('boxSizing') or are we just testing a prop? 30540 if(is(prefixed, "string") || is(prefixed, "undefined")) { 30541 return testProps(props, prefixed); 30542 30543 // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) 30544 } else { 30545 props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); 30546 return testDOMProps(props, prefixed, elem); 30547 } 30548 } 30549 /*>>testallprops*/ 30550 30551 30552 /** 30553 * Tests 30554 * ----- 30555 */ 30556 30557 // The *new* flexbox 30558 // dev.w3.org/csswg/css3-flexbox 30559 30560 tests['flexbox'] = function() { 30561 return testPropsAll('flexWrap'); 30562 }; 30563 30564 // The *old* flexbox 30565 // www.w3.org/TR/2009/WD-css3-flexbox-20090723/ 30566 30567 tests['flexboxlegacy'] = function() { 30568 return testPropsAll('boxDirection'); 30569 }; 30570 30571 // On the S60 and BB Storm, getContext exists, but always returns undefined 30572 // so we actually have to call getContext() to verify 30573 // github.com/Modernizr/Modernizr/issues/issue/97/ 30574 30575 tests['canvas'] = function() { 30576 var elem = document.createElement('canvas'); 30577 return !!(elem.getContext && elem.getContext('2d')); 30578 }; 30579 30580 tests['canvastext'] = function() { 30581 return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function')); 30582 }; 30583 30584 // webk.it/70117 is tracking a legit WebGL feature detect proposal 30585 30586 // We do a soft detect which may false positive in order to avoid 30587 // an expensive context creation: bugzil.la/732441 30588 30589 tests['webgl'] = function() { 30590 return !!window.WebGLRenderingContext; 30591 }; 30592 30593 /* 30594 * The Modernizr.touch test only indicates if the browser supports 30595 * touch events, which does not necessarily reflect a touchscreen 30596 * device, as evidenced by tablets running Windows 7 or, alas, 30597 * the Palm Pre / WebOS (touch) phones. 30598 * 30599 * Additionally, Chrome (desktop) used to lie about its support on this, 30600 * but that has since been rectified: crbug.com/36415 30601 * 30602 * We also test for Firefox 4 Multitouch Support. 30603 * 30604 * For more info, see: modernizr.github.com/Modernizr/touch.html 30605 */ 30606 30607 tests['touch'] = function() { 30608 var bool; 30609 30610 if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { 30611 bool = true; 30612 } else { 30613 injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) { 30614 bool = node.offsetTop === 9; 30615 }); 30616 } 30617 30618 return bool; 30619 }; 30620 30621 30622 // geolocation is often considered a trivial feature detect... 30623 // Turns out, it's quite tricky to get right: 30624 // 30625 // Using !!navigator.geolocation does two things we don't want. It: 30626 // 1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513 30627 // 2. Disables page caching in WebKit: webk.it/43956 30628 // 30629 // Meanwhile, in Firefox < 8, an about:config setting could expose 30630 // a false positive that would throw an exception: bugzil.la/688158 30631 30632 tests['geolocation'] = function() { 30633 return 'geolocation' in navigator; 30634 }; 30635 30636 30637 tests['postmessage'] = function() { 30638 return !!window.postMessage; 30639 }; 30640 30641 30642 // Chrome incognito mode used to throw an exception when using openDatabase 30643 // It doesn't anymore. 30644 tests['websqldatabase'] = function() { 30645 return !!window.openDatabase; 30646 }; 30647 30648 // Vendors had inconsistent prefixing with the experimental Indexed DB: 30649 // - Webkit's implementation is accessible through webkitIndexedDB 30650 // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB 30651 // For speed, we don't test the legacy (and beta-only) indexedDB 30652 tests['indexedDB'] = function() { 30653 return !!testPropsAll("indexedDB", window); 30654 }; 30655 30656 // documentMode logic from YUI to filter out IE8 Compat Mode 30657 // which false positives. 30658 tests['hashchange'] = function() { 30659 return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7); 30660 }; 30661 30662 // Per 1.6: 30663 // This used to be Modernizr.historymanagement but the longer 30664 // name has been deprecated in favor of a shorter and property-matching one. 30665 // The old API is still available in 1.6, but as of 2.0 will throw a warning, 30666 // and in the first release thereafter disappear entirely. 30667 tests['history'] = function() { 30668 return !!(window.history && history.pushState); 30669 }; 30670 30671 tests['draganddrop'] = function() { 30672 var div = document.createElement('div'); 30673 return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); 30674 }; 30675 30676 // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10 30677 // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17. 30678 // FF10 still uses prefixes, so check for it until then. 30679 // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/ 30680 tests['websockets'] = function() { 30681 return 'WebSocket' in window || 'MozWebSocket' in window; 30682 }; 30683 30684 30685 // css-tricks.com/rgba-browser-support/ 30686 tests['rgba'] = function() { 30687 // Set an rgba() color and check the returned value 30688 30689 setCss('background-color:rgba(150,255,150,.5)'); 30690 30691 return contains(mStyle.backgroundColor, 'rgba'); 30692 }; 30693 30694 tests['hsla'] = function() { 30695 // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally, 30696 // except IE9 who retains it as hsla 30697 30698 setCss('background-color:hsla(120,40%,100%,.5)'); 30699 30700 return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla'); 30701 }; 30702 30703 tests['multiplebgs'] = function() { 30704 // Setting multiple images AND a color on the background shorthand property 30705 // and then querying the style.background property value for the number of 30706 // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! 30707 30708 setCss('background:url(https://),url(https://),red url(https://)'); 30709 30710 // If the UA supports multiple backgrounds, there should be three occurrences 30711 // of the string "url(" in the return value for elemStyle.background 30712 30713 return (/(url\s*\(.*?){3}/).test(mStyle.background); 30714 }; 30715 30716 30717 30718 // this will false positive in Opera Mini 30719 // github.com/Modernizr/Modernizr/issues/396 30720 30721 tests['backgroundsize'] = function() { 30722 return testPropsAll('backgroundSize'); 30723 }; 30724 30725 tests['borderimage'] = function() { 30726 return testPropsAll('borderImage'); 30727 }; 30728 30729 30730 // Super comprehensive table about all the unique implementations of 30731 // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance 30732 30733 tests['borderradius'] = function() { 30734 return testPropsAll('borderRadius'); 30735 }; 30736 30737 // WebOS unfortunately false positives on this test. 30738 tests['boxshadow'] = function() { 30739 return testPropsAll('boxShadow'); 30740 }; 30741 30742 // FF3.0 will false positive on this test 30743 tests['textshadow'] = function() { 30744 return document.createElement('div').style.textShadow === ''; 30745 }; 30746 30747 30748 tests['opacity'] = function() { 30749 // Browsers that actually have CSS Opacity implemented have done so 30750 // according to spec, which means their return values are within the 30751 // range of [0.0,1.0] - including the leading zero. 30752 30753 setCssAll('opacity:.55'); 30754 30755 // The non-literal . in this regex is intentional: 30756 // German Chrome returns this value as 0,55 30757 // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 30758 return (/^0.55$/).test(mStyle.opacity); 30759 }; 30760 30761 30762 // Note, Android < 4 will pass this test, but can only animate 30763 // a single property at a time 30764 // goo.gl/v3V4Gp 30765 tests['cssanimations'] = function() { 30766 return testPropsAll('animationName'); 30767 }; 30768 30769 30770 tests['csscolumns'] = function() { 30771 return testPropsAll('columnCount'); 30772 }; 30773 30774 30775 tests['cssgradients'] = function() { 30776 /** 30777 * For CSS Gradients syntax, please see: 30778 * webkit.org/blog/175/introducing-css-gradients/ 30779 * developer.mozilla.org/en/CSS/-moz-linear-gradient 30780 * developer.mozilla.org/en/CSS/-moz-radial-gradient 30781 * dev.w3.org/csswg/css3-images/#gradients- 30782 */ 30783 30784 var str1 = 'background-image:', 30785 str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', 30786 str3 = 'linear-gradient(left top,#9f9, white);'; 30787 30788 setCss( 30789 // legacy webkit syntax (FIXME: remove when syntax not in use anymore) 30790 (str1 + '-webkit- '.split(' ').join(str2 + str1) + 30791 // standard syntax // trailing 'background-image:' 30792 prefixes.join(str3 + str1)).slice(0, -str1.length) 30793 ); 30794 30795 return contains(mStyle.backgroundImage, 'gradient'); 30796 }; 30797 30798 30799 tests['cssreflections'] = function() { 30800 return testPropsAll('boxReflect'); 30801 }; 30802 30803 30804 tests['csstransforms'] = function() { 30805 return !!testPropsAll('transform'); 30806 }; 30807 30808 30809 tests['csstransforms3d'] = function() { 30810 30811 var ret = !!testPropsAll('perspective'); 30812 30813 // Webkit's 3D transforms are passed off to the browser's own graphics renderer. 30814 // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in 30815 // some conditions. As a result, Webkit typically recognizes the syntax but 30816 // will sometimes throw a false positive, thus we must do a more thorough check: 30817 if ( ret && 'webkitPerspective' in docElement.style ) { 30818 30819 // Webkit allows this media query to succeed only if the feature is enabled. 30820 // `@media (transform-3d),(-webkit-transform-3d){ ... }` 30821 injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) { 30822 ret = node.offsetLeft === 9 && node.offsetHeight === 3; 30823 }); 30824 } 30825 return ret; 30826 }; 30827 30828 30829 tests['csstransitions'] = function() { 30830 return testPropsAll('transition'); 30831 }; 30832 30833 30834 /*>>fontface*/ 30835 // @font-face detection routine by Diego Perini 30836 // javascript.nwbox.com/CSSSupport/ 30837 30838 // false positives: 30839 // WebOS github.com/Modernizr/Modernizr/issues/342 30840 // WP7 github.com/Modernizr/Modernizr/issues/538 30841 tests['fontface'] = function() { 30842 var bool; 30843 30844 injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) { 30845 var style = document.getElementById('smodernizr'), 30846 sheet = style.sheet || style.styleSheet, 30847 cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : ''; 30848 30849 bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0; 30850 }); 30851 30852 return bool; 30853 }; 30854 /*>>fontface*/ 30855 30856 // CSS generated content detection 30857 tests['generatedcontent'] = function() { 30858 var bool; 30859 30860 injectElementWithStyles(['#',mod,'{font:0/0 a}
30860#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) { 30861 bool = node.offsetHeight >= 3; 30862 }); 30863 30864 return bool; 30865 }; 30866 30867 30868 30869 // These tests evaluate support of the video/audio elements, as well as 30870 // testing what types of content they support. 30871 // 30872 // We're using the Boolean constructor here, so that we can extend the value 30873 // e.g. Modernizr.video // true 30874 // Modernizr.video.ogg // 'probably' 30875 // 30876 // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845 30877 // thx to NielsLeenheer and zcorpan 30878 30879 // Note: in some older browsers, "no" was a return value instead of empty string. 30880 // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2 30881 // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5 30882 30883 tests['video'] = function() { 30884 var elem = document.createElement('video'), 30885 bool = false; 30886 30887 // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224 30888 try { 30889 if ( bool = !!elem.canPlayType ) { 30890 bool = new Boolean(bool); 30891 bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,''); 30892
vendor: 14,978 bytes, lines 30893-31267
30893 // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546 30894 bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,''); 30895 30896 bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,''); 30897 } 30898 30899 } catch(e) { } 30900 30901 return bool; 30902 }; 30903 30904 tests['audio'] = function() { 30905 var elem = document.createElement('audio'), 30906 bool = false; 30907 30908 try { 30909 if ( bool = !!elem.canPlayType ) { 30910 bool = new Boolean(bool); 30911 bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''); 30912 bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,''); 30913 30914 // Mimetypes accepted: 30915 // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements 30916 // bit.ly/iphoneoscodecs 30917 bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,''); 30918 bool.m4a = ( elem.canPlayType('audio/x-m4a;') || 30919 elem.canPlayType('audio/aac;')) .replace(/^no$/,''); 30920 } 30921 } catch(e) { } 30922 30923 return bool; 30924 }; 30925 30926 30927 // In FF4, if disabled, window.localStorage should === null. 30928 30929 // Normally, we could not test that directly and need to do a 30930 // `('localStorage' in window) && ` test first because otherwise Firefox will 30931 // throw bugzil.la/365772 if cookies are disabled 30932 30933 // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem 30934 // will throw the exception: 30935 // QUOTA_EXCEEDED_ERRROR DOM Exception 22. 30936 // Peculiarly, getItem and removeItem calls do not throw. 30937 30938 // Because we are forced to try/catch this, we'll go aggressive. 30939 30940 // Just FWIW: IE8 Compat mode supports these features completely: 30941 // www.quirksmode.org/dom/html5.html 30942 // But IE8 doesn't support either with local files 30943 30944 tests['localstorage'] = function() { 30945 try { 30946 localStorage.setItem(mod, mod); 30947 localStorage.removeItem(mod); 30948 return true; 30949 } catch(e) { 30950 return false; 30951 } 30952 }; 30953 30954 tests['sessionstorage'] = function() { 30955 try { 30956 sessionStorage.setItem(mod, mod); 30957 sessionStorage.removeItem(mod); 30958 return true; 30959 } catch(e) { 30960 return false; 30961 } 30962 }; 30963 30964 30965 tests['webworkers'] = function() { 30966 return !!window.Worker; 30967 }; 30968 30969 30970 tests['applicationcache'] = function() { 30971 return !!window.applicationCache; 30972 }; 30973 30974 30975 // Thanks to Erik Dahlstrom 30976 tests['svg'] = function() { 30977 return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; 30978 }; 30979 30980 // specifically for SVG inline in HTML, not within XHTML 30981 // test page: paulirish.com/demo/inline-svg 30982 tests['inlinesvg'] = function() { 30983 var div = document.createElement('div'); 30984 div.innerHTML = '<svg/>'; 30985 return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; 30986 }; 30987 30988 // SVG SMIL animation 30989 tests['smil'] = function() { 30990 return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate'))); 30991 }; 30992 30993 // This test is only for clip paths in SVG proper, not clip paths on HTML content 30994 // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg 30995 30996 // However read the comments to dig into applying SVG clippaths to HTML content here: 30997 // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491 30998 tests['svgclippaths'] = function() { 30999 return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath'))); 31000 }; 31001 31002 /*>>webforms*/ 31003 // input features and input types go directly onto the ret object, bypassing the tests loop. 31004 // Hold this guy to execute in a moment. 31005 function webforms() { 31006 /*>>input*/ 31007 // Run through HTML5's new input attributes to see if the UA understands any. 31008 // We're using f which is the <input> element created early on 31009 // Mike Taylr has created a comprehensive resource for testing these attributes 31010 // when applied to all input types: 31011 // miketaylr.com/code/input-type-attr.html 31012 // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary 31013 31014 // Only input placeholder is tested while textarea's placeholder is not. 31015 // Currently Safari 4 and Opera 11 have support only for the input placeholder 31016 // Both tests are available in feature-detects/forms-placeholder.js 31017 Modernizr['input'] = (function( props ) { 31018 for ( var i = 0, len = props.length; i < len; i++ ) { 31019 attrs[ props[i] ] = !!(props[i] in inputElem); 31020 } 31021 if (attrs.list){ 31022 // safari false positive's on datalist: webk.it/74252 31023 // see also github.com/Modernizr/Modernizr/issues/146 31024 attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); 31025 } 31026 return attrs; 31027 })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); 31028 /*>>input*/ 31029 31030 /*>>inputtypes*/ 31031 // Run through HTML5's new input types to see if the UA understands any. 31032 // This is put behind the tests runloop because it doesn't return a 31033 // true/false like all the other tests; instead, it returns an object 31034 // containing each input type with its corresponding true/false value 31035 31036 // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/ 31037 Modernizr['inputtypes'] = (function(props) { 31038 31039 for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) { 31040 31041 inputElem.setAttribute('type', inputElemType = props[i]); 31042 bool = inputElem.type !== 'text'; 31043 31044 // We first check to see if the type we give it sticks.. 31045 // If the type does, we feed it a textual value, which shouldn't be valid. 31046 // If the value doesn't stick, we know there's input sanitization which infers a custom UI 31047 if ( bool ) { 31048 31049 inputElem.value = smile; 31050 inputElem.style.cssText = 'position:absolute;visibility:hidden;'; 31051 31052 if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { 31053 31054 docElement.appendChild(inputElem); 31055 defaultView = document.defaultView; 31056 31057 // Safari 2-4 allows the smiley as a value, despite making a slider 31058 bool = defaultView.getComputedStyle && 31059 defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && 31060 // Mobile android web browser has false positive, so must 31061 // check the height to see if the widget is actually there. 31062 (inputElem.offsetHeight !== 0); 31063 31064 docElement.removeChild(inputElem); 31065 31066 } else if ( /^(search|tel)$/.test(inputElemType) ){ 31067 // Spec doesn't define any special parsing or detectable UI 31068 // behaviors so we pass these through as true 31069 31070 // Interestingly, opera fails the earlier test, so it doesn't 31071 // even make it here. 31072 31073 } else if ( /^(url|email)$/.test(inputElemType) ) { 31074 // Real url and email support comes with prebaked validation. 31075 bool = inputElem.checkValidity && inputElem.checkValidity() === false; 31076 31077 } else { 31078 // If the upgraded input compontent rejects the :) text, we got a winner 31079 bool = inputElem.value != smile; 31080 } 31081 } 31082 31083 inputs[ props[i] ] = !!bool; 31084 } 31085 return inputs; 31086 })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); 31087 /*>>inputtypes*/ 31088 } 31089 /*>>webforms*/ 31090 31091 31092 // End of test definitions 31093 // ----------------------- 31094 31095 31096 31097 // Run through all tests and detect their support in the current UA. 31098 // todo: hypothetically we could be doing an array of tests and use a basic loop here. 31099 for ( var feature in tests ) { 31100 if ( hasOwnProp(tests, feature) ) { 31101 // run the test, throw the return value into the Modernizr, 31102 // then based on that boolean, define an appropriate className 31103 // and push it into an array of classes we'll join later. 31104 featureName = feature.toLowerCase(); 31105 Modernizr[featureName] = tests[feature](); 31106 31107 classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); 31108 } 31109 } 31110 31111 /*>>webforms*/ 31112 // input tests need to run. 31113 Modernizr.input || webforms(); 31114 /*>>webforms*/ 31115 31116 31117 /** 31118 * addTest allows the user to define their own feature tests 31119 * the result will be added onto the Modernizr object, 31120 * as well as an appropriate className set on the html element 31121 * 31122 * @param feature - String naming the feature 31123 * @param test - Function returning true if feature is supported, false if not 31124 */ 31125 Modernizr.addTest = function ( feature, test ) { 31126 if ( typeof feature == 'object' ) { 31127 for ( var key in feature ) { 31128 if ( hasOwnProp( feature, key ) ) { 31129 Modernizr.addTest( key, feature[ key ] ); 31130 } 31131 } 31132 } else { 31133 31134 feature = feature.toLowerCase(); 31135 31136 if ( Modernizr[feature] !== undefined ) { 31137 // we're going to quit if you're trying to overwrite an existing test 31138 // if we were to allow it, we'd do this: 31139 // var re = new RegExp("\\b(no-)?" + feature + "\\b"); 31140 // docElement.className = docElement.className.replace( re, '' ); 31141 // but, no rly, stuff 'em. 31142 return Modernizr; 31143 } 31144 31145 test = typeof test == 'function' ? test() : test; 31146 31147 if (typeof enableClasses !== "undefined" && enableClasses) { 31148 docElement.className += ' ' + (test ? '' : 'no-') + feature; 31149 } 31150 Modernizr[feature] = test; 31151 31152 } 31153 31154 return Modernizr; // allow chaining. 31155 }; 31156 31157 31158 // Reset modElem.cssText to nothing to reduce memory footprint. 31159 setCss(''); 31160 modElem = inputElem = null; 31161 31162 /*>>shiv*/ 31163 /** 31164 * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 31165 */ 31166 ;(function(window, document) { 31167 /*jshint evil:true */ 31168 /** version */ 31169 var version = '3.7.0'; 31170 31171 /** Preset options */ 31172 var options = window.html5 || {}; 31173 31174 /** Used to skip problem elements */ 31175 var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; 31176 31177 /** Not all elements can be cloned in IE **/ 31178 var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; 31179 31180 /** Detect whether the browser supports default html5 styles */ 31181 var supportsHtml5Styles; 31182 31183 /** Name of the expando, to work with multiple documents or to re-shiv one document */ 31184 var expando = '_html5shiv'; 31185 31186 /** The id for the the documents expando */ 31187 var expanID = 0; 31188 31189 /** Cached data for each document */ 31190 var expandoData = {}; 31191 31192 /** Detect whether the browser supports unknown elements */ 31193 var supportsUnknownElements; 31194 31195 (function() { 31196 try { 31197 var a = document.createElement('a'); 31198 a.innerHTML = '<xyz></xyz>'; 31199 //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles 31200 supportsHtml5Styles = ('hidden' in a); 31201 31202 supportsUnknownElements = a.childNodes.length == 1 || (function() { 31203 // assign a false positive if unable to shiv 31204 (document.createElement)('a'); 31205 var frag = document.createDocumentFragment(); 31206 return ( 31207 typeof frag.cloneNode == 'undefined' || 31208 typeof frag.createDocumentFragment == 'undefined' || 31209 typeof frag.createElement == 'undefined' 31210 ); 31211 }()); 31212 } catch(e) { 31213 // assign a false positive if detection fails => unable to shiv 31214 supportsHtml5Styles = true; 31215 supportsUnknownElements = true; 31216 } 31217 31218 }()); 31219 31220 /*--------------------------------------------------------------------------*/ 31221 31222 /** 31223 * Creates a style sheet with the given CSS text and adds it to the document. 31224 * @private 31225 * @param {Document} ownerDocument The document. 31226 * @param {String} cssText The CSS text. 31227 * @returns {StyleSheet} The style element. 31228 */ 31229 function addStyleSheet(ownerDocument, cssText) { 31230 var p = ownerDocument.createElement('p'), 31231 parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; 31232 31233 p.innerHTML = 'x<style>' + cssText + '</style>'; 31234 return parent.insertBefore(p.lastChild, parent.firstChild); 31235 } 31236 31237 /** 31238 * Returns the value of `html5.elements` as an array. 31239 * @private 31240 * @returns {Array} An array of shived element node names. 31241 */ 31242 function getElements() { 31243 var elements = html5.elements; 31244 return typeof elements == 'string' ? elements.split(' ') : elements; 31245 } 31246 31247 /** 31248 * Returns the data associated to the given document 31249 * @private 31250 * @param {Document} ownerDocument The document. 31251 * @returns {Object} An object of data. 31252 */ 31253 function getExpandoData(ownerDocument) { 31254 var data = expandoData[ownerDocument[expando]]; 31255 if (!data) { 31256 data = {}; 31257 expanID++; 31258 ownerDocument[expando] = expanID; 31259 expandoData[expanID] = data; 31260 } 31261 return data; 31262 } 31263 31264 /** 31265 * returns a shived element for the given nodeName and document 31266 * @memberOf html5 31267 * @param {String}
vendor: 4,707 bytes, lines 31267-31378
31267 nodeName name of the element 31268 * @param {Document} ownerDocument The context document. 31269 * @returns {Object} The shived element. 31270 */ 31271 function createElement(nodeName, ownerDocument, data){ 31272 if (!ownerDocument) { 31273 ownerDocument = document; 31274 } 31275 if(supportsUnknownElements){ 31276 return ownerDocument.createElement(nodeName); 31277 } 31278 if (!data) { 31279 data = getExpandoData(ownerDocument); 31280 } 31281 var node; 31282 31283 if (data.cache[nodeName]) { 31284 node = data.cache[nodeName].cloneNode(); 31285 } else if (saveClones.test(nodeName)) { 31286 node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); 31287 } else { 31288 node = data.createElem(nodeName); 31289 } 31290 31291 // Avoid adding some elements to fragments in IE < 9 because 31292 // * Attributes like `name` or `type` cannot be set/changed once an element 31293 // is inserted into a document/fragment 31294 // * Link elements with `src` attributes that are inaccessible, as with 31295 // a 403 response, will cause the tab/window to crash 31296 // * Script elements appended to fragments will execute when their `src` 31297 // or `text` property is set 31298 return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node; 31299 } 31300 31301 /** 31302 * returns a shived DocumentFragment for the given document 31303 * @memberOf html5 31304 * @param {Document} ownerDocument The context document. 31305 * @returns {Object} The shived DocumentFragment. 31306 */ 31307 function createDocumentFragment(ownerDocument, data){ 31308 if (!ownerDocument) { 31309 ownerDocument = document; 31310 } 31311 if(supportsUnknownElements){ 31312 return ownerDocument.createDocumentFragment(); 31313 } 31314 data = data || getExpandoData(ownerDocument); 31315 var clone = data.frag.cloneNode(), 31316 i = 0, 31317 elems = getElements(), 31318 l = elems.length; 31319 for(;i<l;i++){ 31320 clone.createElement(elems[i]); 31321 } 31322 return clone; 31323 } 31324 31325 /** 31326 * Shivs the `createElement` and `createDocumentFragment` methods of the document. 31327 * @private 31328 * @param {Document|DocumentFragment} ownerDocument The document. 31329 * @param {Object} data of the document. 31330 */ 31331 function shivMethods(ownerDocument, data) { 31332 if (!data.cache) { 31333 data.cache = {}; 31334 data.createElem = ownerDocument.createElement; 31335 data.createFrag = ownerDocument.createDocumentFragment; 31336 data.frag = data.createFrag(); 31337 } 31338 31339 31340 ownerDocument.createElement = function(nodeName) { 31341 //abort shiv 31342 if (!html5.shivMethods) { 31343 return data.createElem(nodeName); 31344 } 31345 return createElement(nodeName, ownerDocument, data); 31346 }; 31347 31348 ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' + 31349 'var n=f.cloneNode(),c=n.createElement;' + 31350 'h.shivMethods&&(' + 31351 // unroll the `createElement` calls 31352 getElements().join().replace(/[\w\-]+/g, function(nodeName) { 31353 data.createElem(nodeName); 31354 data.frag.createElement(nodeName); 31355 return 'c("' + nodeName + '")'; 31356 }) + 31357 ');return n}' 31358 )(html5, data.frag); 31359 } 31360 31361 /*--------------------------------------------------------------------------*/ 31362 31363 /** 31364 * Shivs the given document. 31365 * @memberOf html5 31366 * @param {Document} ownerDocument The document to shiv. 31367 * @returns {Document} The shived document. 31368 */ 31369 function shivDocument(ownerDocument) { 31370 if (!ownerDocument) { 31371 ownerDocument = document; 31372 } 31373 var data = getExpandoData(ownerDocument); 31374 31375 if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) { 31376 data.hasCSS = !!addStyleSheet(ownerDocument, 31377 // corrects block display not defined in IE6/7/8/9 31378 'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{dis
31378play:block}' + 31379 // adds styling not present in IE6/7/8/9 31380 'mark{background:#FF0;color:#000}' + 31381 // hides non-rendered elements 31382 'template{display:none}' 31383 ); 31384 } 31385 if (!supportsUnknownElements) { 31386 shivMethods(ownerDocument, data); 31387 } 31388 return ownerDocument; 31389 } 31390 31391 /*--------------------------------------------------------------------------*/ 31392 31393 /** 31394 * The `html5` object is exposed so that more elements can be shived and 31395 * existing shiving can be detected on iframes. 31396 * @type Object 31397 * @example 31398 * 31399 * // options can be changed before the script is included 31400 * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false }; 31401 */ 31402 var html5 = { 31403 31404 /** 31405 * An array or space separated string of node names of the elements to shiv. 31406 * @memberOf html5 31407 * @type Array|String 31408 */ 31409 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video', 31410 31411 /** 31412 * current version of html5shiv 31413 */ 31414 'version': version, 31415 31416 /** 31417 * A flag to indicate that the HTML5 style sheet should be inserted. 31418 * @memberOf html5 31419 * @type Boolean 31420 */ 31421 'shivCSS': (options.shivCSS !== false), 31422 31423 /** 31424 * Is equal to true if a browser supports creating unknown/HTML5 elements 31425 * @memberOf html5 31426 * @type boolean 31427 */ 31428 'supportsUnknownElements': supportsUnknownElements, 31429 31430 /** 31431 * A flag to indicate that the document's `createElement` and `createDocumentFragment` 31432 * methods should be overwritten. 31433 * @memberOf html5 31434 * @type Boolean 31435 */ 31436 'shivMethods': (options.shivMethods !== false), 31437 31438 /** 31439 * A string to describe the type of `html5` object ("default" or "default print"). 31440 * @memberOf html5
31441 * @type String 31442 */ 31443 'type': 'default', 31444 31445 // shivs the document according to the specified `html5` object options 31446 'shivDocument': shivDocument, 31447 31448 //creates a shived element 31449 createElement: createElement, 31450 31451 //creates a shived documentFragment 31452 createDocumentFragment: createDocumentFragment 31453 }; 31454 31455 /*--------------------------------------------------------------------------*/ 31456 31457 // expose html5 31458 window.html5 = html5; 31459 31460 // shiv the document 31461 shivDocument(document); 31462 31463 }(this, document)); 31464 /*>>shiv*/ 31465 31466 // Assign private properties to the return object with prefix 31467 Modernizr._version = version; 31468 31469 // expose these for the plugin API. Look in the source for how to join() them against your input 31470 /*>>prefixes*/ 31471 Modernizr._prefixes = prefixes; 31472 /*>>prefixes*/ 31473 /*>>domprefixes*/ 31474 Modernizr._domPrefixes = domPrefixes; 31475 Modernizr._cssomPrefixes = cssomPrefixes; 31476 /*>>domprefixes*/ 31477 31478 /*>>mq*/ 31479 // Modernizr.mq tests a given media query, live against the current state of the window 31480 // A few important notes: 31481 // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false 31482 // * A max-width or orientation query will be evaluated against the current state, which may change later. 31483 // * You must specify values. Eg. If you are testing support for the min-width media query use: 31484 // Modernizr.mq('(min-width:0)') 31485 // usage: 31486 // Modernizr.mq('only screen and (max-width:768)') 31487 Modernizr.mq = testMediaQuery; 31488 /*>>mq*/ 31489 31490 /*>>hasevent*/ 31491 // Modernizr.hasEvent() detects support for a given event, with an optional element to test on 31492 // Modernizr.hasEvent('gesturestart', elem) 31493 Modernizr.hasEvent = isEventSupported; 31494 /*>>hasevent*/ 31495 31496 /*>>testprop*/ 31497 // Modernizr.testProp() investigates whether a given style property is recognized 31498 // Note that the property names must be provided in the camelCase variant. 31499 // Modernizr.testProp('pointerEvents') 31500 Modernizr.testProp = function(prop){ 31501 return testProps([prop]); 31502 }; 31503 /*>>testprop*/ 31504 31505 /*>>testallprops*/ 31506 // Modernizr.testAllProps() investigates whether a given style property, 31507 // or any of its vendor-prefixed variants, is recognized 31508 // Note that the property names must be provided in the camelCase variant. 31509 // Modernizr.testAllProps('boxSizing') 31510 Modernizr.testAllProps = testPropsAll; 31511 /*>>testallprops*/ 31512 31513 31514 /*>>teststyles*/ 31515 // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards 31516 // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... }) 31517 Modernizr.testStyles = injectElementWithStyles; 31518 /*>>teststyles*/ 31519 31520 31521 /*>>prefixed*/ 31522 // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input 31523 // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' 31524 31525 // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style. 31526 // Return values will also be the camelCase variant, if you need to translate that to hypenated style use: 31527 // 31528 // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); 31529 31530 // If you're trying to ascertain which transition end event to bind to, you might do something like... 31531 // 31532 // var transEndEventNames = { 31533 // 'WebkitTransition' : 'webkitTransitionEnd', 31534 // 'MozTransition' : 'transitionend', 31535 // 'OTransition' : 'oTransitionEnd', 31536 // 'msTransition' : 'MSTransitionEnd', 31537 // 'transition' : 'transitionend' 31538 // }, 31539 // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; 31540 31541 Modernizr.prefixed = function(prop, obj, elem){ 31542 if(!obj) { 31543 return testPropsAll(prop, 'pfx'); 31544 } else { 31545 // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' 31546 return testPropsAll(prop, obj, elem); 31547 } 31548 }; 31549 /*>>prefixed*/ 31550 31551 31552 /*>>cssclasses*/ 31553 // Remove "no-js" class from <html> element, if it exists: 31554 docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + 31555 31556 // Add the new classes to the <html> element. 31557 (enableClasses ? ' js ' + classes.join(' ') : ''); 31558 /*>>cssclasses*/ 31559 31560 return Modernizr; 31561 31562})(this, this.document); 31563; 31564 31565/*! Agility 31566*/ 31567 31568 31569if (typeof (window.Agility) == "undefined") { 31570 window.Agility = new Object(); 31571} 31572(function(Agility) { 31573 31574 //handle ctrl and shift 31575 Agility.isCtrl = false; 31576 Agility.isAlt = false; 31577 Agility.isShift = false; 31578 31579 $(document).keyup(function (e) { 31580 switch (e.which) { 31581 case 16: 31582 Agility.isShift=false; 31583 break; 31584 case 17: 31585 Agility.isCtrl=false; 31586 break; 31587 case 18: 31588 Agility.isAlt=false; 31589 break; 31590 } 31591 31592 }).keydown(function (e) { 31593 switch (e.which) { 31594 case 16: 31595 Agility.isShift=true; 31596 break; 31597 case 17: 31598 Agility.isCtrl=true; 31599 break; 31600 case 18: 31601 Agility.isAlt=true; 31602 break; 31603 } 31604 31605 }); 31606 31607 31608 Agility.RegisterNamespace = function(space) { 31609 /// <summary> 31610 /// Register a javascript namespace. 31611 /// </summary> 31612 /// <param name="space" type="String">The namespace (dot-separated) to register.</param> 31613 /// <returns type="object">Object representing the created namespace.</returns> 31614 31615 var spaces = space.split("."), 31616 root = window; 31617 31618 for (var i = 0; i < spaces.length; i++) { 31619 if (typeof (root[spaces[i]]) == "undefined") { 31620 root = root[spaces[i]] = {}; 31621 } else { 31622 root = root[spaces[i]]; 31623 } 31624 } 31625 31626 return root; 31627 } 31628 31629 var _sessionLevelCacheKey = null; 31630 Agility.SessionLevelCacheKey = function() { 31631 /// <summary> 31632 /// gets a string that is based on the date and time that this page was loaded. Use this for Client Templating with urls. 31633 /// </summary> 31634 31635 if (_sessionLevelCacheKey == null) {
31636 _sessionLevelCacheKey = (new Date()).toString("yyyyMMddHHmmss"); 31637 } 31638 return _sessionLevelCacheKey; 31639 31640 }; 31641 31642 Agility.ResolveUrl = function(url) { 31643 /// <summary> 31644 /// Resolve "~/" to the application's base url. *Requires that global var "Edentity_BaseUrl" has been set. 31645 /// </summary> 31646 /// <param name="url" type="String">The URL whose path to resolve.</param> 31647 /// <returns type="string">String representing the resolved URL.</returns> 31648 31649 var baseUrl = window.Agility_BaseUrl || "/"; 31650 return url.replace(/^~\//, baseUrl); 31651 } 31652 31653 31654 var _unique = {}; 31655 var _uniqueIndex = 0; 31656 Agility.UniqueID = function(prePend){ 31657 /// <summary> 31658 /// Build a Unique ID (unique to this instance). 31659 /// </summary> 31660 /// <param name="prePend" type="String">The value to prepend to the Unique portion.</param> 31661 31662 if (prePend == undefined || prePend == null || prePend == "") { 31663 return _uniqueIndex++; 31664 } else { 31665 if (_unique[prePend] == undefined) _unique[prePend] = 0; 31666 return prePend + _unique[prePend]++; 31667 } 31668 } 31669 31670 Agility.CloneObject = function (what, serializationType) { 31671 /// <summary> 31672 /// Clones an object to preserve the original value. 31673 /// </summary> 31674 /// <param name="what" type="object">The object to clone.</param> 31675 31676 if (serializationType != undefined && serializationType != null && serializationType != "") { 31677 this.__type = serializationType; 31678 } 31679 31680 for (i in what) { 31681 if (what[i] == null) { 31682 this[i] = null; 31683 } else { 31684 31685 if (typeof what[i] == 'object') { 31686 this[i] = new Agility.CloneObject(what[i]); 31687 } else { 31688 var val = what[i]; 31689 this[i] = val; 31690 } 31691 } 31692 } 31693 } 31694 31695 31696 31697 Agility.QueryString = function(name, url) { 31698 /// <summary> 31699 /// Gets a variable from the query string. 31700 /// </summary> 31701 /// <param name="name" type="String">QueryString variable to retrieve.</param> 31702 /// <param name="url" type="String">(Optional) the url to take the querystring from. If this is not present, the current url is used.</param> 31703 31704 if (url == undefined || url == null || url == "") { 31705 url = location.href; 31706 } 31707 31708 var index = url.indexOf("?"); 31709 if (index < 1 && index == url.length - 2) return null; 31710 if (url.indexOf("#") != -1) { 31711 url = url.substring(0, url.indexOf("#")); 31712 } 31713 31714 var qstr = url.substring(index + 1, url.length); 31715 31716 var ary1 = qstr.split("&"); 31717 var retValue = null; 31718 31719 jQuery.each(ary1, function(index, q) { 31720 var ary2 = q.split("="); 31721 if (ary2.length == 2) { 31722 if (unescape(ary2[0]).toLowerCase() == name.toLowerCase()) { 31723 31724 retValue = ary2[1]; 31725 retValue = retValue.replace(/\+/g, "%20"); 31726 retValue = unescape(retValue); 31727 return false; 31728 } 31729 } 31730 }); 31731 31732 return retValue; 31733 31734 } 31735 31736 Agility.ToJSONDate = function(dateObj) { 31737 /// <summary> 31738 /// Converts a Date object to a JSON string, and it will account for the timezone offset (\/Date(000000000000)\/). 31739 /// </summary> 31740 /// <param name="dateObj" type="Date">Date object to convert.</param> 31741 31742 dateObj.setMinutes(dateObj.getMinutes() + dateObj.getTimezoneOffset()); 31743 31744 var dtStr = dateObj.getFullYear() + "-" + Agility.PadLeft(dateObj.getMonth() + 1, "0") + "-" + Agility.PadLeft(dateObj.getDate() + 1, "0") + " " + Agility.PadLeft(dateObj.getHours(), "0") + ":" + Agility.PadLeft(dateObj.getMinutes(), "0") + ":" + Agility.PadLeft(dateObj.getSeconds(), dateObj.getMilliseconds(), "0"); 31745 31746 return "\/Date("+ dtStr +")\/"; 31747 } 31748 31749 Agility.PadLeft = function(str, padChar) { 31750 31751 str = str + ""; 31752 while (str.length < padChar) { 31753 str = padChar + str; 31754 } 31755 31756 return str; 31757 } 31758 31759 Agility.GetFlashVersion = function() { 31760 31761 var flashVersion = 0; 31762 31763 if (window.ActiveXObject) { 31764 //ie 31765 var control = null; 31766 try { 31767 control = new ActiveXObject('ShockwaveFlash.ShockwaveFlash'); 31768 if (control) { 31769 var version = control.GetVariable('$version').substring(4); 31770 version = version.split(','); 31771 flashVersion = parseInt(version[0]); 31772 } 31773 } catch (e) { 31774 } 31775 31776 } else { 31777 31778 //non ie 31779 if (navigator.plugins != null) { 31780 if (navigator.plugins.length > 0) { 31781 var flashPlugin = navigator.plugins['Shockwave Flash']; 31782 31783 if (typeof flashPlugin == 'object') { 31784 if (flashPlugin.version) { 31785 var vstr = flashPlugin.version; 31786 if (vstr) flashVersion = parseInt(vstr.split(".")[0]); 31787 } else { 31788 var desc = flashPlugin.description; 31789 if (desc) flashVersion = parseInt(desc.replace("Shockwave Flash ", "").split(".")[0]); 31790 } 31791 } 31792 } 31793 } 31794 } 31795 31796 return flashVersion; 31797 } 31798 31799
31800 31801 Agility.SetCookie = function(name, value, expires, path, domain, secure ) { 31802 /// <summary>Sets a cookie based on the name and value provided.</summary> 31803 /// <param name="name" type="String">The name of the cookie to set the value of.</param> 31804 /// <param name="value" type="String">The value of the cookie to set.</param> 31805 /// <param name="expires" type="Date">(Optional) The date that the cookie should expire.</param> 31806 /// <param name="path" type="String">(Optional) The path of the cookie.</param> 31807 /// <param name="domain" type="String">(Optional) The domain of the cookie.</param> 31808 /// <param name="secure" type="Boolean">(Optional) Whether the cookie is secure or not.</param> 31809 31810 var expires_date = expires; 31811 31812 document.cookie = name + "=" +escape( value ) + 31813 ( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) + 31814 ( ( path ) ? ";path=" + path : "" ) + 31815 ( ( domain ) ? ";domain=" + domain : "" ) + 31816 ( ( secure ) ? ";secure" : "" ); 31817 } 31818 31819 31820 31821 Agility.GetCookie = function ( cookieName ) { 31822 /// <summary>Gets the value of the given cookieName from the current cookies collection.</summary> 31823 /// <param name="cookieName" type="String">The name of the cookie to return.</param> 31824 31825 // first we'll split this cookie up into name/value pairs 31826 // note: document.cookie only returns name=value, not the other components 31827 var a_all_cookies = document.cookie.split( ';' ); 31828 var a_temp_cookie = ''; 31829 var cookie_name = ''; 31830 var cookie_value = ''; 31831 var b_cookie_found = false; // set boolean t/f default f 31832 31833 for ( i = 0; i < a_all_cookies.length; i++ ) 31834 { 31835 // now we'll split apart each name=value pair 31836 a_temp_cookie = a_all_cookies[i].split( '=' ); 31837 31838 31839 // and trim left/right whitespace while we're at it 31840 cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, ''); 31841 31842 // if the extracted name matches passed cookieName 31843 if ( cookie_name == cookieName ) 31844 { 31845 b_cookie_found = true; 31846 // we need to handle case where cookie has no value but exists (no = sign, that is): 31847 if ( a_temp_cookie.length > 1 ) 31848 { 31849 cookie_value = unescape( a_temp_cookie[1].replace(/^\s+|\s+$/g, '') ); 31850 } 31851 // note that in cases where cookie is initialized but no value, null is returned 31852 return cookie_value; 31853 break; 31854 } 31855 a_temp_cookie = null; 31856 cookie_name = ''; 31857 } 31858 if ( !b_cookie_found ) 31859 { 31860 return null; 31861 } 31862 } 31863 31864 Agility.DeleteCookie = function(name, path, domain, secure) { 31865 /// <summary>Delete a cookie based on the name provided.</summary> 31866 /// <param name="name" type="String">The name of the cookie to set the value of.</param> 31867 /// <param name="path" type="String">(Optional) The path of the cookie.</param> 31868 /// <param name="domain" type="String">(Optional) The domain of the cookie.</param> 31869 /// <param name="secure" type="Boolean">(Optional) Whether the cookie is secure or not.</param> 31870 31871 if (Agility.GetCookie(name)) { 31872 document.cookie = name + "=" + (path ? ";path=" + path : "") + 31873 (domain ? ";domain=" + domain : "" ) + (secure ? ";secure" : "") + 31874 ";expires=Thu, 01-Jan-1970 00:00:01 GMT"; 31875 } 31876 }; 31877 31878 31879 Agility.JSON = new function () { 31880 31881 /* Section: Methods - Public */ 31882 31883 /* 31884 Method: decode 31885 decodes a valid JSON encoded string. 31886 31887 Arguments: 31888 [String / Function] - Optional JSON string to decode or a filter function if method is a String prototype. 31889 [Function] - Optional filter function if first argument is a JSON string and this method is not a String prototype. 31890 31891 Returns: 31892 Object - Generic JavaScript variable or undefined 31893 31894 Example [Basic]: 31895 >var arr = JSON.decode('[1,2,3]'); 31896 >alert(arr); // 1,2,3 31897 > 31898 >arr = JSON.decode('[1,2,3]', function(key, value){return key * value}); 31899 >alert(arr); // 0,2,6 31900 31901 Example [Prototype]: 31902 >String.prototype.parseJSON = JSON.decode; 31903 > 31904 >alert('[1,2,3]'.parseJSON()); // 1,2,3 31905 > 31906 >try { 31907 > alert('[1,2,3]'.parseJSON(function(key, value){return key * value})); 31908 > // 0,2,6 31909 >} 31910 >catch(e) { 31911 > alert(e.message); 31912 >} 31913 31914 Note: 31915 Internet Explorer 5 and other old browsers should use a different regular expression to check if a JSON string is valid or not. 31916 This old browsers dedicated RegExp is not safe as native version is but it required for compatibility. 31917 */ 31918 this.decode = function () { 31919 var filter, result, self, tmp; 31920 if ($$("toString")) { 31921 switch (arguments.length) { 31922 case 2: 31923 self = arguments[0]; 31924 filter = arguments[1]; 31925 break; 31926 case 1: 31927 if ($[typeof arguments[0]](arguments[0]) === Function) { 31928 self = this; 31929 filter = arguments[0]; 31930 } 31931 else 31932 self = arguments[0]; 31933 break; 31934 default: 31935 self = this; 31936 break; 31937 }; 31938 if (rc.test(self)) { 31939 try { 31940 result = e("(".concat(self, ")")); 31941 if (filter && result !== null && (tmp = $[typeof result](result)) && (tmp === Array || tmp === Object)) { 31942 for (self in result) 31943 result[self] = v(self, result) ? filter(self, result[self]) : result[self]; 31944 } 31945 } 31946 catch (z) { } 31947 } 31948 else { 31949 throw new JSONError("bad data"); 31950 } 31951 }; 31952 return result; 31953 }; 31954 31955 /* 31956 Method: encode 31957 encode a generic JavaScript variable into a valid JSON string. 31958 31959 Arguments: 31960 [Object] - Optional generic JavaScript variable to encode if method is not an Object prototype. 31961 31962 Returns: 31963 String - Valid JSON string or undefined 31964 31965 Example [Basic]: 31966 >var s = Agility.JSON.encode([1,2,3]); 31967 >alert(s); // [1,2,3] 31968 31969 Example [Prototype]: 31970 >Object.prototype.toJSONString = Agility.JSON.encode; 31971 > 31972 >alert([1,2,3].toJSONString()); // [1,2,3] 31973 */ 31974 this.encode = function () { 31975 var self = arguments.length ? arguments[0] : this, 31976 result, tmp; 31977 if (self === null) 31978 result = "null"; 31979 else if (self !== undefined && (tmp = $[typeof self](self))) { 31980 switch (tmp) { 31981 case Array: 31982 result = []; 31983 for (var i = 0, j = 0, k = self.length; j < k; j++) { 31984 if (self[j] !== undefined && (tmp = Agility.JSON.encode(self[j]))) 31985 result[i++] = tmp; 31986 }; 31987 result = "[".concat(result.join(","), "]"); 31988 break; 31989 case Boolean: 31990 result = String(self); 31991 break; 31992 case Date: 31993 result = '"'.concat(self.getFullYear(), '-', d(self.getMonth() + 1), '-', d(self.getDate()), 'T', d(self.getHours()), ':', d(self.getMinutes()), ':', d(self.getSeconds()), '"'); 31994 break; 31995 case Function: 31996 break; 31997 case Number: 31998 result = isFinite(self) ? String(self) : "null"; 31999 break; 32000 case String: 32001 result = '"'.concat(self.replace(rs, s).replace(ru, u), '"'); 32002 break; 32003 default: 32004 var i = 0, key; 32005 result = []; 32006 for (key in self) { 32007 if (self[key] !== undefined && (tmp = Agility.JSON.encode(self[key]))) 32008 result[i++] = '"'.concat(key.replace(rs, s).replace(ru, u), '":', tmp); 32009 }; 32010 result = "{".concat(result.join(","), "}"); 32011 break; 32012 } 32013 }; 32014 return result; 32015 }; 32016 32017 /* 32018 Method: toDate
32019 transforms a JSON encoded Date string into a native Date object. 32020 32021 Arguments: 32022 [String/Number] - Optional JSON Date string or server time if this method is not a String prototype. Server time should be an integer, based on seconds since 1970/01/01 or milliseconds / 1000 since 1970/01/01. 32023 32024 Returns: 32025 Date - Date object or undefined if string is not a valid Date 32026 32027 Example [Basic]: 32028 >var serverDate = JSON.toDate("2007-04-05T08:36:46"); 32029 >alert(serverDate.getMonth()); // 3 (months start from 0) 32030 32031 Example [Prototype]: 32032 >String.prototype.parseDate = JSON.toDate; 32033 > 32034 >alert("2007-04-05T08:36:46".parseDate().getDate()); // 5 32035 32036 Example [Server Time]: 32037 >var phpServerDate = JSON.toDate(<?php echo time(); ?>); 32038 >var csServerDate = JSON.toDate(<%=(DateTime.Now.Ticks/10000-62135596800000)%>/1000); 32039 32040 Example [Server Time Prototype]: 32041 >Number.prototype.parseDate = JSON.toDate; 32042 >var phpServerDate = (<?php echo time(); ?>).parseDate(); 32043 >var csServerDate = (<%=(DateTime.Now.Ticks/10000-62135596800000)%>/1000).parseDate(); 32044 32045 Note: 32046 This method accepts an integer or numeric string too to mantain compatibility with generic server side time() function. 32047 You can convert quickly mtime, ctime, time and other time based values. 32048 With languages that supports milliseconds you can send total milliseconds / 1000 (time is set as time * 1000) 32049 */ 32050 this.toDate = function () { 32051 var self = arguments.length ? arguments[0] : this, 32052 result; 32053 if (rd.test(self)) { 32054 result = new Date; 32055 result.setHours(i(self, 11, 2)); 32056 result.setMinutes(i(self, 14, 2)); 32057 result.setSeconds(i(self, 17, 2)); 32058 result.setMonth(i(self, 5, 2) - 1); 32059 result.setDate(i(self, 8, 2)); 32060 result.setFullYear(i(self, 0, 4)); 32061 } 32062 else if (rt.test(self)) 32063 result = new Date(self * 1000); 32064 return result; 32065 }; 32066 32067 /* Section: Properties - Private */ 32068 32069 /* 32070 Property: Private 32071 32072 List: 32073 Object - 'c' - a dictionary with useful keys / values for fast encode convertion 32074 Function - 'd' - returns decimal string rappresentation of a number ("14", "03", etc) 32075 Function - 'e' - safe and native code evaulation 32076 Function - 'i' - returns integer from string ("01" => 1, "15" => 15, etc) 32077 Array - 'p' - a list with different "0" strings for fast special chars escape convertion 32078 RegExp - 'rc' - regular expression to check JSON strings (different for IE5 or old browsers and new one) 32079 RegExp - 'rd' - regular expression to check a JSON Date string 32080 RegExp - 'rs' - regular expression to check string chars to modify using c (char) values 32081 RegExp - 'rt' - regular expression to check integer numeric string (for toDate time version evaluation) 32082 RegExp - 'ru' - regular expression to check string chars to escape using "\u" prefix 32083 Function - 's' - returns escaped string adding "\\" char as prefix ("\\" => "\\\\", etc.) 32084 Function - 'u' - returns escaped string, modifyng special chars using "\uNNNN" notation 32085 Function - 'v' - returns boolean value to skip object methods or prototyped parameters (length, others), used for optional decode filter function 32086 Function - '$' - returns object constructor if it was not cracked (someVar = {}; someVar.constructor = String <= ignore them) 32087 Function - '$$' - returns boolean value to check native Array and Object constructors before convertion 32088 */ 32089 var c = { "\b": "b", "\t": "t", "\n": "n", "\f": "f", "\r": "r", '"': '"', "\\": "\\", "/": "/" }, 32090 d = function (n) { return n < 10 ? "0".concat(n) : n }, 32091 e = function (c, f, e) { e = eval; delete eval; if (typeof eval === "undefined") eval = e; f = eval("" + c); eval = e; return f }, 32092 i = function (e, p, l) { return 1 * e.substr(p, l) }, 32093 p = ["", "000", "00", "0", ""], 32094 rc = null, 32095 rd = /^[0-9]{4}\-[0-9]{2}\-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/, 32096 rs = /(\x5c|\x2F|\x22|[\x0c-\x0d]|[\x08-\x0a])/g, 32097 rt = /^([0-9]+|[0-9]+[,\.][0-9]{1,3})$/, 32098 ru = /([\x00-\x07]|\x0b|[\x0e-\x1f])/g, 32099 s = function (i, d) { return "\\".concat(c[d]) }, 32100 u = function (i, d) { 32101 var n = d.charCodeAt(0).toString(16); 32102 return "\\u".concat(p[n.length], n) 32103 }, 32104 v = function (k, v) { return $[typeof result](result) !== Function && (v.hasOwnProperty ? v.hasOwnProperty(k) : v.constructor.prototype[k] !== v[k]) }, 32105 $ = { 32106 "boolean": function () { return Boolean }, 32107 "function": function () { return Function }, 32108 "number": function () { return Number }, 32109 "object": function (o) { return o instanceof o.constructor ? o.constructor : null }, 32110 "string": function () { return String }, 32111 "undefined": function () { return null } 32112 }, 32113 $$ = function (m) { 32114 function $(c, t) { t = c[m]; delete c[m]; try { e(c) } catch (z) { c[m] = t; return 1 } }; 32115 return $(Array) && $(Object) 32116 }; 32117 try { rc = new RegExp('^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$') } 32118 catch (z) { rc = /^(true|false|null|\[.*\]|\{.*\}|".*"|\d+|\d+\.\d+)$/ } 32119 }; 32120 32121 32122})(Agility); 32123 32124 32125//include datejs here 32126var tryParseDate = Date.parse; 32127Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Frid
32127ay","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|aft(er)?|from|hence)/i,subtract:/^(\-|bef(ore)?|ago)/i,yesterday:/^yes(terday)?/i,today:/^t(od(ay)?)?/i,tomorrow:/^tom(orrow)?/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^mn|min(ute)?s?/i,hour:/^h(our)?s?/i,week:/^w(eek)?s?/i,month:/^m(onth)?s?/i,day:/^d(ay)?s?/i,year:/^y(ear)?s?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt|utc)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a(?!u|p)|p)/i},timezones:[{name:"UTC",offset:"-000"},{name:"GMT",offset:"-000"},{name:"EST",offset:"-0500"},{name:"EDT",offset:"-0400"},{name:"CST",offset:"-0600"},{name:"CDT",offset:"-0500"},{name:"MST",offset:"-0700"},{name:"MDT",offset:"-0600"},{name:"PST",offset:"-0800"},{name:"PDT",offset:"-0700"}]};(function(){var $D=Date,$P=$D.prototype,$C=$D.CultureInfo,p=function(s,l){if(!l){l=2;}return("000"+s).slice(l*-1);};$P.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};$P.setTimeToNow=function(){var n=new Date();this.setHours(n.getHours());this.setMinutes(n.getMinutes());this.setSeconds(n.getSeconds());this.setMilliseconds(n.getMilliseconds());return this;};$D.today=function(){return new Date().clearTime();};$D.compare=function(date1,date2){if(isNaN(date1)||isNaN(date2)){throw new Error(date1+" - "+date2);}else{if(date1 instanceof Date&&date2 instanceof Date){return(date1<date2)?-1:(date1>date2)?1:0;}else{throw new TypeError(date1+" - "+date2);}}};$D.equals=function(date1,date2){return(date1.compareTo(date2)===0);};$D.getDayNumberFromName=function(name){var n=$C.dayNames,m=$C.abbreviatedDayNames,o=$C.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s||o[i].toLowerCase()==s){return i;}}return -1;};$D.getMonthNumberFromName=function(name){var n=$C.monthNames,m=$C.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}return -1;};$D.isLeapYear=function(year){return((year%4===0&&year%100!==0)||year%400===0);};$D.getDaysInMonth=function(year,month){return[31,($D.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};$D.getTimezoneAbbreviation=function(offset){var z=$C.timezones,p;for(var i=0;i<z.length;i++){if(z[i].offset===offset){return z[i].name;}}return null;};$D.getTimezoneOffset=function(name){var z=$C.timezones,p;for(var i=0;i<z.length;i++){if(z[i].name===name.toUpperCase()){return z[i].offset;}}return null;};$P.clone=function(){return new Date(this.getTime());};$P.compareTo=function(date){return Date.compare(this,date);};$P.equals=function(date){return Date.equals(this,date||new Date());};$P.between=function(start,end){return this.getTime()>=start.getTime()&&this.getTime()<=end.getTime();};$P.isAfter=function(date){return this.compareTo(date||new Date())===1;};$P.isBefore=function(date){return(this.compareTo(date||new Date())===-1);};$P.isToday=$P.isSameDay=function(date){return this.clone().clearTime().equals((date||new Date()).clone().clearTime());};$P.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value*1);return this;};$P.addSeconds=function(value){return this.addMilliseconds(value*1000);};$P.addMinutes=function(value){return this.addMilliseconds(value*60000);};$P.addHours=function(value){return this.addMilliseconds(value*3600000);};$P.addDays=function(value){this.setDate(this.getDate()+value*1);return this;};$P.addWeeks=function(value){return this.addDays(value*7);};$P.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value*1);this.setDate(Math.min(n,$D.getDaysInMonth(this.getFullYear(),this.getMonth())));return this;};$P.addYears=function(value){return this.addMonths(value*12);};$P.add=function(config){if(typeof config=="number"){this._orient=config;return this;}var x=config;if(x.milliseconds){this.addMilliseconds(x.milliseconds);}if(x.seconds){this.addSeconds(x.seconds);}if(x.minutes){this.addMinutes(x.minutes);}if(x.hours){this.addHours(x.hours);}if(x.weeks){this.addWeeks(x.weeks);}if(x.months){this.addMonths(x.months);}if(x.years){this.addYears(x.years);}if(x.days){this.addDays(x.days);}return this;};var $y,$m,$d;$P.getWeek=function(){var a,b,c,d,e,f,g,n,s,w;$y=(!$y)?this.getFullYear():$y;$m=(!$m)?this.getMonth()+1:$m;$d=(!$d)?this.getDate():$d;if($m<=2){a=$y-1;b=(a/4|0)-(a/100|0)+(a/400|0);c=((a-1)/4|0)-((a-1)/100|0)+((a-1)/400|0);s=b-c;e=0;f=$d-1+(31*($m-1));}else{a=$y;b=(a/4|0)-(a/100|0)+(a/400|0);c=((a-1)/4|0)-((a-1)/100|0)+((a-1)/400|0);s=b-c;e=s+1;f=$d+((153*($m-3)+2)/5)+58+s;}g=(a+b)%7;d=(f+g-e)%7;n=(f+3-d)|0;if(n<0){w=53-((g-s)/5|0);}else{if(n>364+s){w=1;}else{w=(n/7|0)+1;}}$y=$m=$d=null;return w;};$P.getISOWeek=function(){$y=this.getUTCFullYear();$m=this.getUTCMonth()+1;$d=this.getUTCDate();return p(this.getWeek());};
32127$P.setWeek=function(n){return this.moveToDayOfWeek(1).addWeeks(n-this.getWeek());};var validate=function(n,min,max,name){if(typeof n=="undefined"){return false;}else{if(typeof n!="number"){throw new TypeError(n+" is not a Number.");}else{if(n<min||n>max){throw new RangeError(n+" is not a valid value for "+name+".");}}}return true;};$D.validateMillisecond=function(value){return validate(value,0,999,"millisecond");};$D.validateSecond=function(value){return validate(value,0,59,"second");};$D.validateMinute=function(value){return validate(value,0,59,"minute");};$D.validateHour=function(value){return validate(value,0,23,"hour");};$D.validateDay=function(value,year,month){return validate(value,1,$D.getDaysInMonth(year,month),"day");};$D.validateMonth=function(value){return validate(value,0,11,"month");};$D.validateYear=function(value){return validate(value,0,9999,"year");};$P.set=function(config){if($D.validateMillisecond(config.millisecond)){this.addMilliseconds(config.millisecond-this.getMilliseconds());}if($D.validateSecond(config.second)){this.addSeconds(config.second-this.getSeconds());}if($D.validateMinute(config.minute)){this.addMinutes(config.minute-this.getMinutes());}if($D.validateHour(config.hour)){this.addHours(config.hour-this.getHours());}if($D.validateMonth(config.month)){this.addMonths(config.month-this.getMonth());}if($D.validateYear(config.year)){this.addYears(config.year-this.getFullYear());}if($D.validateDay(config.day,this.getFullYear(),this.getMonth())){this.addDays(config.day-this.getDate());}if(config.timezone){this.setTimezone(config.timezone);}if(config.timezoneOffset){this.setTimezoneOffset(config.timezoneOffset);}if(config.week&&validate(config.week,0,53,"week")){this.setWeek(config.week);}return this;};$P.moveToFirstDayOfMonth=function(){return this.set({day:1});};$P.moveToLastDayOfMonth=function(){return this.set({day:$D.getDaysInMonth(this.getFullYear(),this.getMonth())});};$P.moveToNthOccurrence=function(dayOfWeek,occurrence){var shift=0;if(occurrence>0){shift=occurrence-1;}else{if(occurrence===-1){this.moveToLastDayOfMonth();if(this.getDay()!==dayOfWeek){this.moveToDayOfWeek(dayOfWeek,-1);}return this;}}return this.moveToFirstDayOfMonth().addDays(-1).moveToDayOfWeek(dayOfWeek,+1).addWeeks(shift);};$P.moveToDayOfWeek=function(dayOfWeek,orient){var diff=(dayOfWeek-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};$P.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};$P.getOrdinalNumber=function(){return Math.ceil((this.clone().clearTime()-new Date(this.getFullYear(),0,1))/86400000)+1;};$P.getTimezone=function(){return $D.getTimezoneAbbreviation(this.getUTCOffset());};$P.setTimezoneOffset=function(offset){var here=this.getTimezoneOffset(),there=Number(offset)*-6/10;return this.addMinutes(there-here);};$P.setTimezone=function(offset){return this.setTimezoneOffset($D.getTimezoneOffset(offset));};$P.hasDaylightSavingTime=function(){return(Date.today().set({month:0,day:1}).getTimezoneOffset()!==Date.today().set({month:6,day:1}).getTimezoneOffset());};$P.isDaylightSavingTime=function(){return Date.today().set({month:0,day:1}).getTimezoneOffset()!=this.getTimezoneOffset();};$P.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r.charAt(0)+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};$P.getElapsed=function(date){return(date||new Date())-this;};if(!$P.toISOString){$P.toISOString=function(){function f(n){return n<10?"0"+n:n;}return'"'+this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+'Z"';};}$P._toString=$P.toString;$P.toString=function(format){var x=this;if(format&&format.length==1){var c=$C.formatPatterns;x.t=x.toString;switch(format){case"d":return x.t(c.shortDate);case"D":return x.t(c.longDate);case"F":return x.t(c.fullDateTime);case"m":return x.t(c.monthDay);case"r":return x.t(c.rfc1123);case"s":return x.t(c.sortableDateTime);case"t":return x.t(c.shortTime);case"T":return x.t(c.longTime);case"u":return x.t(c.universalSortableDateTime);case"y":return x.t(c.yearMonth);}}var ord=function(n){switch(n*1){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};return format?format.replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S)/g,function(m){if(m.charAt(0)==="\\"){return m.replace("\\","");}x.h=x.getHours;switch(m){case"hh":return p(x.h()<13?(x.h()===0?12:x.h()):(x.h()-12));case"h":return x.h()<13?(x.h()===0?12:x.h()):(x.h()-12);case"HH":return p(x.h());case"H":return x.h();case"mm":return p(x.getMinutes());case"m":return x.getMinutes();case"ss":return p(x.getSeconds());
32127case"s":return x.getSeconds();case"yyyy":return p(x.getFullYear(),4);case"yy":return p(x.getFullYear());case"dddd":return $C.dayNames[x.getDay()];case"ddd":return $C.abbreviatedDayNames[x.getDay()];case"dd":return p(x.getDate());case"d":return x.getDate();case"MMMM":return $C.monthNames[x.getMonth()];case"MMM":return $C.abbreviatedMonthNames[x.getMonth()];case"MM":return p((x.getMonth()+1));case"M":return x.getMonth()+1;case"t":return x.h()<12?$C.amDesignator.substring(0,1):$C.pmDesignator.substring(0,1);case"tt":return x.h()<12?$C.amDesignator:$C.pmDesignator;case"S":return ord(x.getDate());default:return m;}}):this._toString();};}());(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^s*"+s+"s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}break;}return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}rx.push(r[0]);s=r[1];}return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}try{r=(px[i].call(this,s));}catch(e){r=null;}if(r){return r;}}throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}rx.push(r[0]);s=r[1];}return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}s=q[1];}if(!r){throw new $P.Exception(s);}if(q){throw new $P.Exception(q[1]);}if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}if(!last&&q[1].length===0){last=true;}if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}if(rx[1].length<best[1].length){best=rx;}if(best[1].length===0){break;}}if(best[0].length===0){return best;}if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}best[1]=q[1];}return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else{if(arguments[0] instanceof Array){args=arguments[0];}}if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}var _vector=function(op){return function(){if(arguments[0] instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var $D=Date,$P=$D.prototype,$C=$D.CultureInfo;var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i] instanceof Array){rx=rx.concat(flattenAndCompact(ax[i])
32127);}else{if(ax[i]){rx.push(ax[i]);}}}return rx;};$D.Grammar={};$D.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=(s.length==3)?"jan feb mar apr may jun jul aug sep oct nov dec".indexOf(s)/4:Number(s)-1;};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<$C.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}var now=new Date();if((this.hour||this.minute)&&(!this.month&&!this.year&&!this.day)){this.day=now.getDate();}if(!this.year){this.year=now.getFullYear();}if(!this.month&&this.month!==0){this.month=now.getMonth();}if(!this.day){this.day=1;}if(!this.hour){this.hour=0;}if(!this.minute){this.minute=0;}if(!this.second){this.second=0;}if(this.meridian&&this.hour){if(this.meridian=="p"&&this.hour<12){this.hour=this.hour+12;}else{if(this.meridian=="a"&&this.hour==12){this.hour=0;}}}if(this.day>$D.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else{if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}}return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}var today=$D.today();if(this.now&&!this.unit&&!this.operator){return new Date();}else{if(this.now){today=new Date();}}var expression=!!(this.days&&this.days!==null||this.orient||this.operator);var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(!this.now&&"hour minute second".indexOf(this.unit)!=-1){today.setTimeToNow();}if(this.month||this.month===0){if("year day hour minute second".indexOf(this.unit)!=-1){this.value=this.month+1;this.month=null;expression=true;}}if(!expression&&this.weekday&&!this.day&&!this.days){var temp=Date[this.weekday]();this.day=temp.getDate();if(!this.month){this.month=temp.getMonth();}this.year=temp.getFullYear();}if(expression&&this.weekday&&this.unit!="month"){this.unit="day";gap=($D.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}if(this.month&&this.unit=="day"&&this.operator){this.value=(this.month+1);this.month=null;}if(this.value!=null&&this.month!=null&&this.year!=null){this.day=this.value*1;}if(this.month&&!this.day&&this.value){today.set({day:this.value*1});if(!expression){this.day=this.value*1;}}if(!this.month&&this.value&&this.unit=="month"&&!this.now){this.month=this.value;expression=true;}if(expression&&(this.month||this.month===0)&&this.unit!="year"){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}if(!this.unit){this.unit="day";}if(!this.value&&this.operator&&this.operator!==null&&this[this.unit+"s"]&&this[this.unit+"s"]!==null){this[this.unit+"s"]=this[this.unit+"s"]+((this.operator=="add")?1:-1)+(this.value||0)*orient;}else{if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}this[this.unit+"s"]=this.value*orient;}}if(this.meridian&&this.hour){if(this.meridian=="p"&&this.hour<12){this.hour=this.hour+12;}else{if(this.meridian=="a"&&this.hour==12){this.hour=0;}}}if(this.weekday&&!this.day&&!this.days){var temp=Date[this.weekday]();this.day=temp.getDate();if(temp.getMonth()!==today.getMonth()){this.month=temp.getMonth();}}if((this.month||this.month===0)&&!this.day){this.day=1;}if(!this.orient&&!this.operator&&this.unit=="week"&&this.value&&!this.day&&!this.month){return Date.today().setWeek(this.value);}if(expression&&this.timezone&&this.day&&this.days){this.day=this.days;}return(expression)?today.add(this):today.set(this);}};var _=$D.Parsing.Operators,g=$D.Grammar,t=$D.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|@|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=$C.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;
32127i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}fn=_C[keys]=_.any.apply(null,px);}return fn;};g.ctoken2=function(key){return _.rtoken($C.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.m,g.s],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("second minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[$C.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw $D.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(['"yyyy-MM-ddTHH:mm:ssZ"',"yyyy-MM-ddTHH:mm:ssZ","yyyy-MM-ddTHH:mm:ssz","yyyy-MM-ddTHH:mm:ss","yyyy-MM-ddTHH:mmZ","yyyy-MM-ddTHH:mmz","yyyy-MM-ddTHH:mm","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","MMddyyyy","ddMMyyyy","Mddyyyy","ddMyyyy","Mdyyyy","dMyyyy","yyyy","Mdyy","dMyy","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}return g._start.call({},s);};$D._parse=$D.parse;$D.parse=function(s){var r=null;if(!s){return null;}if(s instanceof Date){return s;}try{r=$D.Grammar.start.call({},s.replace(/^\s*(\S*(\s+\S+)*)\s*$/,"$1"));}catch(e){return null;}try { return((r[1].length===0)?r[0]:Date._parse(s)); } catch (er1) {return tryParseDate(s);};};$D.getParseFunction=function(fx){var fn=$D.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}return((r[1].length===0)?r[0]:null);};};$D.parseExact=function(s,fx){return $D.getParseFunction(fx)(s);};}());(function(){var $D=Date,$P=$D.prototype,$C=$D.CultureInfo,$N=Number.prototype;$P._orient=+1;$P._nth=null;$P._is=false;$P._same=false;$P._isSecond=false;$N._dateElement="day";$P.next=function(){this._orient=+1;return this;};$D.next=function(){return $D.today().next();};$P.last=$P.prev=$P.previous=function(){this._orient=-1;return this;};
32127$D.last=$D.prev=$D.previous=function(){return $D.today().last();};$P.is=function(){this._is=true;return this;};$P.same=function(){this._same=true;this._isSecond=false;return this;};$P.today=function(){return this.same().day();};$P.weekday=function(){if(this._is){this._is=false;return(!this.is().sat()&&!this.is().sun());}return false;};$P.at=function(time){return(typeof time==="string")?$D.parse(this.toString("d")+" "+time):this.set(time);};$N.fromNow=$N.after=function(date){var c={};c[this._dateElement]=this;return((!date)?new Date():date.clone()).add(c);};$N.ago=$N.before=function(date){var c={};c[this._dateElement]=this*-1;return((!date)?new Date():date.clone()).add(c);};var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),pxf=("Milliseconds Seconds Minutes Hours Date Week Month FullYear").split(/\s/),nth=("final first second third fourth fifth").split(/\s/),de;$P.toObject=function(){var o={};for(var i=0;i<px.length;i++){o[px[i].toLowerCase()]=this["get"+pxf[i]]();}return o;};$D.fromObject=function(config){config.week=null;return Date.today().set(config);};var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}if(this._nth!==null){if(this._isSecond){this.addSeconds(this._orient*-1);}this._isSecond=false;var ntemp=this._nth;this._nth=null;var temp=this.clone().moveToLastDayOfMonth();this.moveToNthOccurrence(n,ntemp);if(this>temp){throw new RangeError($D.getDayName(n)+" does not occur "+ntemp+" times in the month of "+$D.getMonthName(temp.getMonth())+" "+temp.getFullYear()+".");}return this;}return this.moveToDayOfWeek(n,this._orient);};};var sdf=function(n){return function(){var t=$D.today(),shift=n-t.getDay();if(n===0&&$C.firstDayOfWeek===1&&t.getDay()!==0){shift=shift+7;}return t.addDays(shift);};};for(var i=0;i<dx.length;i++){$D[dx[i].toUpperCase()]=$D[dx[i].toUpperCase().substring(0,3)]=i;$D[dx[i]]=$D[dx[i].substring(0,3)]=sdf(i);$P[dx[i]]=$P[dx[i].substring(0,3)]=df(i);}var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}return this.moveToMonth(n,this._orient);};};var smf=function(n){return function(){return $D.today().set({month:n,day:1});};};for(var j=0;j<mx.length;j++){$D[mx[j].toUpperCase()]=$D[mx[j].toUpperCase().substring(0,3)]=j;$D[mx[j]]=$D[mx[j].substring(0,3)]=smf(j);$P[mx[j]]=$P[mx[j].substring(0,3)]=mf(j);}var ef=function(j){return function(){if(this._isSecond){this._isSecond=false;return this;}if(this._same){this._same=this._is=false;var o1=this.toObject(),o2=(arguments[0]||new Date()).toObject(),v="",k=j.toLowerCase();for(var m=(px.length-1);m>-1;m--){v=px[m].toLowerCase();if(o1[v]!=o2[v]){return false;}if(k==v){break;}}return true;}if(j.substring(j.length-1)!="s"){j+="s";}return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$P[de]=$P[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}$P._ss=ef("Second");var nthfn=function(n){return function(dayOfWeek){if(this._same){return this._ss(arguments[0]);}if(dayOfWeek||dayOfWeek===0){return this.moveToNthOccurrence(dayOfWeek,n);}this._nth=n;if(n===2&&(dayOfWeek===undefined||dayOfWeek===null)){this._isSecond=true;return this.addSeconds(this._orient);}return this;};};for(var l=0;l<nth.length;l++){$P[nth[l]]=(l===0)?nthfn(-1):nthfn(l);}}());var TimeSpan=function(days,hours,minutes,seconds,milliseconds){var attrs="days hours minutes seconds milliseconds".split(/\s+/);var gFn=function(attr){return function(){return this[attr];};};var sFn=function(attr){return function(val){this[attr]=val;return this;};};for(var i=0;i<attrs.length;i++){var $a=attrs[i],$b=$a.slice(0,1).toUpperCase()+$a.slice(1);TimeSpan.prototype[$a]=0;TimeSpan.prototype["get"+$b]=gFn($a);TimeSpan.prototype["set"+$b]=sFn($a);}if(arguments.length==4){this.setDays(days);this.setHours(hours);this.setMinutes(minutes);this.setSeconds(seconds);}
32127else{if(arguments.length==5){this.setDays(days);this.setHours(hours);this.setMinutes(minutes);this.setSeconds(seconds);this.setMilliseconds(milliseconds);}else{if(arguments.length==1&&typeof days=="number"){var orient=(days<0)?-1:+1;this.setMilliseconds(Math.abs(days));this.setDays(Math.floor(this.getMilliseconds()/86400000)*orient);this.setMilliseconds(this.getMilliseconds()%86400000);this.setHours(Math.floor(this.getMilliseconds()/3600000)*orient);this.setMilliseconds(this.getMilliseconds()%3600000);this.setMinutes(Math.floor(this.getMilliseconds()/60000)*orient);this.setMilliseconds(this.getMilliseconds()%60000);this.setSeconds(Math.floor(this.getMilliseconds()/1000)*orient);this.setMilliseconds(this.getMilliseconds()%1000);this.setMilliseconds(this.getMilliseconds()*orient);}}}this.getTotalMilliseconds=function(){return(this.getDays()*86400000)+(this.getHours()*3600000)+(this.getMinutes()*60000)+(this.getSeconds()*1000);};this.compareTo=function(time){var t1=new Date(1970,1,1,this.getHours(),this.getMinutes(),this.getSeconds()),t2;if(time===null){t2=new Date(1970,1,1,0,0,0);}else{t2=new Date(1970,1,1,time.getHours(),time.getMinutes(),time.getSeconds());}return(t1<t2)?-1:(t1>t2)?1:0;};this.equals=function(time){return(this.compareTo(time)===0);};this.add=function(time){return(time===null)?this:this.addSeconds(time.getTotalMilliseconds()/1000);};this.subtract=function(time){return(time===null)?this:this.addSeconds(-time.getTotalMilliseconds()/1000);};this.addDays=function(n){return new TimeSpan(this.getTotalMilliseconds()+(n*86400000));};this.addHours=function(n){return new TimeSpan(this.getTotalMilliseconds()+(n*3600000));};this.addMinutes=function(n){return new TimeSpan(this.getTotalMilliseconds()+(n*60000));};this.addSeconds=function(n){return new TimeSpan(this.getTotalMilliseconds()+(n*1000));};this.addMilliseconds=function(n){return new TimeSpan(this.getTotalMilliseconds()+n);};this.get12HourHour=function(){return(this.getHours()>12)?this.getHours()-12:(this.getHours()===0)?12:this.getHours();};this.getDesignator=function(){return(this.getHours()<12)?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;};this.toString=function(format){this._toString=function(){if(this.getDays()!==null&&this.getDays()>0){return this.getDays()+"."+this.getHours()+":"+this.p(this.getMinutes())+":"+this.p(this.getSeconds());}else{return this.getHours()+":"+this.p(this.getMinutes())+":"+this.p(this.getSeconds());}};this.p=function(s){return(s.toString().length<2)?"0"+s:s;};var me=this;return format?format.replace(/dd?|HH?|hh?|mm?|ss?|tt?/g,function(format){switch(format){case"d":return me.getDays();case"dd":return me.p(me.getDays());case"H":return me.getHours();case"HH":return me.p(me.getHours());case"h":return me.get12HourHour();case"hh":return me.p(me.get12HourHour());case"m":return me.getMinutes();case"mm":return me.p(me.getMinutes());case"s":return me.getSeconds();case"ss":return me.p(me.getSeconds());case"t":return((me.getHours()<12)?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator).substring(0,1);case"tt":return(me.getHours()<12)?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;}}):this._toString();};return this;};Date.prototype.getTimeOfDay=function(){return new TimeSpan(0,this.getHours(),this.getMinutes(),this.getSeconds(),this.getMilliseconds());};var TimePeriod=function(years,months,days,hours,minutes,seconds,milliseconds){var attrs="years months days hours minutes seconds milliseconds".split(/\s+/);var gFn=function(attr){return function(){return this[attr];};};var sFn=function(attr){return function(val){this[attr]=val;return this;};};for(var i=0;i<attrs.length;i++){var $a=attrs[i],$b=$a.slice(0,1).toUpperCase()+$a.slice(1);TimePeriod.prototype[$a]=0;TimePeriod.prototype["get"+$b]=gFn($a);TimePeriod.prototype["set"+$b]=sFn($a);}if(arguments.length==7){this.years=years;this.months=months;this.setDays(days);this.setHours(hours);this.setMinutes(minutes);this.setSeconds(seconds);this.setMilliseconds(milliseconds);}else{if(arguments.length==2&&arguments[0] instanceof Date&&arguments[1] instanceof Date){var d1=years.clone();var d2=months.clone();var temp=d1.clone();var orient=(d1>d2)?-1:+1;this.years=d2.getFullYear()-d1.getFullYear();temp.addYears(this.years);if(orient==+1){if(temp>d2){if(this.years!==0){this.years--;}}}else{if(temp<d2){if(this.years!==0){this.years++;}}}d1.addYears(this.years);if(orient==+1){while(d1<d2&&d1.clone().addDays(Date.getDaysInMonth(d1.getYear(),d1.getMonth()))<d2){d1.addMonths(1);this.months++;}}else{while(d1>d2&&d1.clone().addDays(-d1.getDaysInMonth())>d2){d1.addMonths(-1);this.months--;}}var diff=d2-d1;if(diff!==0){var ts=new TimeSpan(diff);this.setDays(ts.getDays());this.setHours(ts.getHours());this.setMinutes(ts.getMinutes());this.setSeconds(ts.getSeconds());this.setMilliseconds(ts.getMilliseconds());}}}return this;}; 32128 32129; 32130/* 32131 * base64.js 32132 * 32133 * Licensed under the BSD 3-Clause License. 32134 * http://opensource.org/licenses/BSD-3-Clause 32135 * 32136 * References: 32137 * http://en.wikipedia.org/wiki/Base64 32138 */ 32139;(function (global, factory) { 32140 typeof exports === 'object' && typeof module !== 'undefined' 32141 ? module.exports = factory(global) 32142 : typeof define === 'function' && define.amd 32143 ? define(factory) : factory(global) 32144}(( 32145 typeof self !== 'undefined' ? self 32146 : typeof window !== 'undefined' ? window 32147 : typeof global !== 'undefined' ? global 32148: this 32149), function(global) { 32150 'use strict'; 32151 // existing version for noConflict() 32152 global = global || {}; 32153 var _Base64 = global.Base64; 32154 var version = "2.5.2"; 32155 // if node.js and NOT React Native, we use Buffer 32156 var buffer; 32157 if (typeof module !== 'undefined' && module.exports) { 32158 try { 32159 buffer = eval("require('buffer').Buffer"); 32160 } catch (err) { 32161 buffer = undefined; 32162 } 32163 } 32164 // constants 32165 var b64chars 32166 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
32166+/'; 32167 var b64tab = function(bin) { 32168 var t = {}; 32169 for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i; 32170 return t; 32171 }(b64chars); 32172 var fromCharCode = String.fromCharCode; 32173 // encoder stuff 32174 var cb_utob = function(c) { 32175 if (c.length < 2) { 32176 var cc = c.charCodeAt(0); 32177 return cc < 0x80 ? c 32178 : cc < 0x800 ? (fromCharCode(0xc0 | (cc >>> 6)) 32179 + fromCharCode(0x80 | (cc & 0x3f))) 32180 : (fromCharCode(0xe0 | ((cc >>> 12) & 0x0f)) 32181 + fromCharCode(0x80 | ((cc >>> 6) & 0x3f)) 32182 + fromCharCode(0x80 | ( cc & 0x3f))); 32183 } else { 32184 var cc = 0x10000 32185 + (c.charCodeAt(0) - 0xD800) * 0x400 32186 + (c.charCodeAt(1) - 0xDC00); 32187 return (fromCharCode(0xf0 | ((cc >>> 18) & 0x07)) 32188 + fromCharCode(0x80 | ((cc >>> 12) & 0x3f)) 32189 + fromCharCode(0x80 | ((cc >>> 6) & 0x3f)) 32190 + fromCharCode(0x80 | ( cc & 0x3f))); 32191 } 32192 }; 32193 var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g; 32194 var utob = function(u) { 32195 return u.replace(re_utob, cb_utob); 32196 }; 32197 var cb_encode = function(ccc) { 32198 var padlen = [0, 2, 1][ccc.length % 3], 32199 ord = ccc.charCodeAt(0) << 16 32200 | ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8) 32201 | ((ccc.length > 2 ? ccc.charCodeAt(2) : 0)), 32202 chars = [ 32203 b64chars.charAt( ord >>> 18), 32204 b64chars.charAt((ord >>> 12) & 63), 32205 padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63), 32206 padlen >= 1 ? '=' : b64chars.charAt(ord & 63) 32207 ]; 32208 return chars.join(''); 32209 }; 32210 var btoa = global.btoa ? function(b) { 32211 return global.btoa(b); 32212 } : function(b) { 32213 return b.replace(/[\s\S]{1,3}/g, cb_encode); 32214 }; 32215 var _encode = function(u) { 32216 var isUint8Array = Object.prototype.toString.call(u) === '[object Uint8Array]'; 32217 return isUint8Array ? u.toString('base64') 32218 : btoa(utob(String(u))); 32219 } 32220 var encode = function(u, urisafe) { 32221 return !urisafe 32222 ? _encode(u) 32223 : _encode(String(u)).replace(/[+\/]/g, function(m0) { 32224 return m0 == '+' ? '-' : '_'; 32225 }).replace(/=/g, ''); 32226 }; 32227 var encodeURI = function(u) { return encode(u, true) }; 32228 // decoder stuff 32229 var re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g; 32230 var cb_btou = function(cccc) { 32231 switch(cccc.length) { 32232 case 4: 32233 var cp = ((0x07 & cccc.charCodeAt(0)) << 18) 32234 | ((0x3f & cccc.charCodeAt(1)) << 12) 32235 | ((0x3f & cccc.charCodeAt(2)) << 6) 32236 | (0x3f & cccc.charCodeAt(3)), 32237 offset = cp - 0x10000; 32238 return (fromCharCode((offset >>> 10) + 0xD800) 32239 + fromCharCode((offset & 0x3FF) + 0xDC00)); 32240 case 3: 32241 return fromCharCode( 32242 ((0x0f & cccc.charCodeAt(0)) << 12) 32243 | ((0x3f & cccc.charCodeAt(1)) << 6) 32244 | (0x3f & cccc.charCodeAt(2)) 32245 ); 32246 default: 32247 return fromCharCode( 32248 ((0x1f & cccc.charCodeAt(0)) << 6) 32249 | (0x3f & cccc.charCodeAt(1)) 32250 ); 32251 } 32252 }; 32253 var btou = function(b) { 32254 return b.replace(re_btou, cb_btou); 32255 }; 32256 var cb_decode = function(cccc) { 32257 var len = cccc.length, 32258 padlen = len % 4, 32259 n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0) 32260 | (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0) 32261 | (len > 2 ? b64tab[cccc.charAt(2)] << 6 : 0) 32262 | (len > 3 ? b64tab[cccc.charAt(3)] : 0), 32263 chars = [ 32264 fromCharCode( n >>> 16), 32265 fromCharCode((n >>> 8) & 0xff), 32266 fromCharCode( n & 0xff) 32267 ]; 32268 chars.length -= [0, 0, 2, 1][padlen]; 32269 return chars.join(''); 32270 }; 32271 var _atob = global.atob ? function(a) { 32272 return global.atob(a); 32273 } : function(a){ 32274 return a.replace(/\S{1,4}/g, cb_decode); 32275 }; 32276 var atob = function(a) { 32277 return _atob(String(a).replace(/[^A-Za-z0-9\+\/]/g, '')); 32278 }; 32279 var _decode = buffer ? 32280 buffer.from && Uint8Array && buffer.from !== Uint8Array.from 32281 ? function(a) { 32282 return (a.constructor === buffer.constructor 32283 ? a : buffer.from(a, 'base64')).toString(); 32284 } 32285 : function(a) { 32286 return (a.constructor === buffer.constructor 32287 ? a : new buffer(a, 'base64')).toString(); 32288 } 32289 : function(a) { return btou(_atob(a)) }; 32290 var decode = function(a){ 32291 return _decode( 32292 String(a).replace(/[-_]/g, function(m0) { return m0 == '-' ? '+' : '/' }) 32293 .replace(/[^A-Za-z0-9\+\/]/g, '') 32294 ); 32295 }; 32296 var noConflict = function() { 32297 var Base64 = global.Base64; 32298 global.Base64 = _Base64; 32299 return Base64; 32300 }; 32301 // export Base64 32302 global.Base64 = { 32303 VERSION: version, 32304 atob: atob, 32305 btoa: btoa, 32306 fromBase64: decode, 32307 toBase64: encode,
32308 utob: utob, 32309 encode: encode, 32310 encodeURI: encodeURI, 32311 btou: btou, 32312 decode: decode, 32313 noConflict: noConflict, 32314 __buffer__: buffer 32315 }; 32316 // if ES5 is available, make Base64.extendString() available 32317 if (typeof Object.defineProperty === 'function') { 32318 var noEnum = function(v){ 32319 return {value:v,enumerable:false,writable:true,configurable:true}; 32320 }; 32321 global.Base64.extendString = function () { 32322 Object.defineProperty( 32323 String.prototype, 'fromBase64', noEnum(function () { 32324 return decode(this) 32325 })); 32326 Object.defineProperty( 32327 String.prototype, 'toBase64', noEnum(function (urisafe) { 32328 return encode(this, urisafe) 32329 })); 32330 Object.defineProperty( 32331 String.prototype, 'toBase64URI', noEnum(function () { 32332 return encode(this, true) 32333 })); 32334 }; 32335 } 32336 // 32337 // export Base64 to the namespace 32338 // 32339 if (global['Meteor']) { // Meteor.js 32340 Base64 = global.Base64; 32341 } 32342 // module.exports and AMD are mutually exclusive. 32343 // module.exports has precedence. 32344 if (typeof module !== 'undefined' && module.exports) { 32345 module.exports.Base64 = global.Base64; 32346 } 32347 else if (typeof define === 'function' && define.amd) { 32348 // AMD. Register as an anonymous module. 32349 define([], function(){ return global.Base64 }); 32350 } 32351 // that's it! 32352 return {Base64: global.Base64} 32353})); 32354 32355 32356Agility.RegisterNamespace('Agility.FormBuilder'); 32357 32358(function (FormBuilder) { 32359 32360 FormBuilder.Bootstrap = '.agility-form-clearfix{clear: both;}.agility-form{clear: both;}.agility-form .agility-form-row{width:100%;margin-bottom: 5px;}.agility-form .agility-form-col-full,.agility-form .agility-form-col-half,.agility-form .agility-form-col-quarter,.agility-form .agility-form-col-third{position:relative;min-height:1px;padding-left:15px;padding-right:15px;width:100%}@media (min-width:768px){.agility-form .agility-form-col-full,.agility-form .agility-form-col-half,.agility-form .agility-form-col-quarter,.agility-form .agility-form-col-third{float:left}.agility-form .agility-form-col-full{width:100%}.agility-form .agility-form-col-half{width:50%}.agility-form .agility-form-col-third{width:33.33333333%}.agility-form .agility-form-col-quarter{width:25%}}.agility-form label,.agility-form input[type="text"],.agility-form input[type="email"],.agility-form input[type="number"],.agility-form input[type="date"],.agility-form input[type="file"],.agility-form select,.agility-form textarea{line-height:inherit;width:100%;}.agility-form textarea{min-height:150px;}.agility-form label.agility-form-checkbox-label{font-weight:normal;}.agility-form-checkbox-label span{margin-left: 5px;}.agility-form-submit-btn {margin-top: 5px;}'; 32361 FormBuilder.Base64 = { encode: function (e) { return Base64.encode(e); }, decode: function (e) { return Base64.decode(e); } } 32362 32363 /// <summary> 32364 /// Gets/Sets HTML markup of the from 32365 /// </summary> 32366 /// <param name="textBlob">Text blob that stores additionaljson and fieldTypes</param> 32367 /// <param name="htmlContainerID">ID of the html element that the form will be injected to</param> 32368 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter which is the html markup.</param> 32369 FormBuilder.GetHTMLMarkup = function (textBlob, htmlContainerID, currentMode, callback) { 32370 var textBlobObj = JSON.parse(FormBuilder.Base64.decode(textBlob)); 32371 32372 if (!window.FormBuilderValues) { 32373 window.FormBuilderValues = {}; 32374 } 32375 32376 var values = textBlobObj.values; 32377 32378 window.FormBuilderValues[htmlContainerID] = values; 32379 window.FormBuilderContainerName = textBlobObj.uniqueID; 32380 32381 32382 var contentID = textBlobObj.contentID; 32383 var mode = parseInt(currentMode); 32384 var languageCode = textBlobObj.languageCode; 32385 var recordTypeID = values.RecordTypeID; 32386 var additionalJSON = values.AdditionalJSON; 32387 var fieldTypes = textBlobObj.fieldTypes; 32388 var formSelector = '#' + htmlContainerID + ' form'; 32389 32390 var html = '<div><form class="agility-form" data-agility-form-content-id="' + contentID + '">'; 32391 32392 //add bootstrap scoped 32393 html += '<style scoped>' + FormBuilder.Bootstrap + '</style>'; 32394 32395 //there is additional styling 32396 if (values.ThemeID > 0) { 32397 html += FormBuilder.GetThemeStyleMarkup(values, formSelector); 32398 } 32399 32400 var rows = []; 32401 var currentRow = { 32402 columns: [] 32403 }; 32404 32405 var currentWidth = 0; 32406 32407 for (var i = 0; i < fieldTypes.length; i++) { 32408 var fieldType = fieldTypes[i];
32409 32410 if (fieldType.DataType === 9999 && fieldType.JSONFields.InlineCodeLanguage !== 'html') { 32411 if (fieldType.JSONFields.InlineCodeLanguage === 'javascript') { 32412 html += '<script type="text/javascript">' + fieldType.JSONFields.InlineCode + '</script>'; 32413 } else { 32414 //css 32415 html += '<style scoped>' + fieldType.JSONFields.InlineCode + '</style>'; 32416 } 32417 } else { 32418 var width = FormBuilder.GetColumnWidth(fieldType.JSONFields.ColumnWidth); 32419 32420 if (currentWidth + width > 1.0) { 32421 //clone the current row 32422 rows.push(JSON.parse(JSON.stringify(currentRow))); 32423 currentRow.columns = []; 32424 currentWidth = 0; 32425 } 32426 32427 currentRow.columns.push({ width: fieldType.JSONFields.ColumnWidth, fieldType: fieldType }); 32428 currentWidth += width; 32429 } 32430 } 32431 32432 rows.push(currentRow); 32433 32434 for (var i = 0; i < rows.length; i++) { 32435 var row = rows[i]; 32436 32437 html += FormBuilder.GetRowMarkup(row.columns, contentID); 32438 } 32439 32440 html += FormBuilder.GetSubmitButtonMarkup(values.SubmitButtonLabel, formSelector, contentID, languageCode, mode, recordTypeID); 32441 32442 html += '<div class="agility-form-clearfix"><div>' 32443 html += '</form></div>'; 32444 html += '<div class="agility-form-clearfix"><div>' 32445 32446 //return the html markup 32447 if (callback) { 32448 callback(html); 32449 } else if (htmlContainerID) { 32450 $('#' + htmlContainerID).html(html); 32451 } 32452 32453 if (window.Parsley) { 32454 FormBuilder.ConfigureParsley(formSelector); 32455 } else { 32456 $.getScript("https://media.agilitycms.com/form-builder/parsley.min.js", function () { 32457 FormBuilder.ConfigureParsley(formSelector); 32458 }); 32459 } 32460 }; 32461 32462 FormBuilder.ConfigureParsley = function (formSelector) { 32463 $(formSelector).parsley({ 32464 excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden], .parsley-ignore', 32465 }); 32466 }; 32467 32468 FormBuilder.GetRowMarkup = function (columns, contentID) { 32469 32470 var html = '<div class="agility-form-row">'; 32471 32472 for (var i = 0; i < columns.length; i++) { 32473 var column = columns[i]; 32474 32475 if (column.fieldType.DataType === 9999) { 32476 html += '<div class="agility-form-col-full">' + column.fieldType.JSONFields.InlineCode + '</div>'; 32477 } else { 32478 html += FormBuilder.GetColumnMarkup(column, contentID); 32479 } 32480 } 32481 32482 html += '<div class="agility-form-clearfix"></div>'; 32483 html += '</div>'; 32484 32485 return html; 32486 } 32487 32488 FormBuilder.GetThemeStyleMarkup = function (values, formSelector) { 32489 var html = "<style scoped>"; 32490 32491 //form 32492 html += formSelector + '{' 32493 + FormBuilder.GetCSSRule('font-family', values.FormFontFamily) 32494 + FormBuilder.GetCSSRule('background-color', values.FormBackgroun
32494dColor) 32495 + FormBuilder.GetCSSRule('padding', values.FormPadding) 32496 + FormBuilder.GetCSSRule('margin', values.FormMargin) 32497 + FormBuilder.GetCSSRule('border', values.FormBorder) 32498 + '}'; 32499 32500 //input 32501 html += formSelector + ' input:not([type=checkbox]), ' 32502 + formSelector + ' select, ' 32503 + formSelector + ' textarea ' 32504 + '{' 32505 + FormBuilder.GetCSSRule('background-color', values.InputBackgroundColor) 32506 + FormBuilder.GetCSSRule('font-size', values.InputFontSize) 32507 + FormBuilder.GetCSSRule('color', values.InputFontColor) 32508 + FormBuilder.GetCSSRule('height', values.InputHeight) 32509 + FormBuilder.GetCSSRule('margin-top', values.InputMarginTop) 32510 + FormBuilder.GetCSSRule('margin-bottom', values.InputMarginBottom) 32511 + FormBuilder.GetCSSRule('outline', values.InputOutline) 32512 + FormBuilder.GetCSSRule('border', values.InputBorder) 32513 + FormBuilder.GetCSSRule('border-radius', values.InputBorderRadius) 32514 + FormBuilder.GetCSSRule('padding', values.InputPadding) 32515 + '}'; 32516 32517 html += formSelector + ' input:not([type=checkbox]):focus, ' 32518 + formSelector + ' select:focus,' 32519 + formSelector + ' textarea:focus' 32520 + '{' 32521 + FormBuilder.GetCSSRule('border', values.InputFocusedBorder) 32522 + '}'; 32523 32524 //label 32525 html += formSelector + ' label{' 32526 + FormBuilder.GetCSSRule('font-size', values.LabelFontSize) 32527 + FormBuilder.GetCSSRule('color', values.LabelFontColor) 32528 + FormBuilder.GetCSSRule('font-weight', values.LabelFontWeight) 32529 + FormBuilder.GetCSSRule('margin', values.LabelMargin) 32530 + FormBuilder.GetCSSRule('padding', values.LabelPadding) 32531 + '}'; 32532 32533 //button 32534 html += formSelector + ' button{' 32535 + FormBuilder.GetCSSRule('background-color', values.ButtonBackgroundColor) 32536 + FormBuilder.GetCSSRule('color', values.ButtonFontColor) 32537 + FormBuilder.GetCSSRule('font-size', values.ButtonFontSize) 32538 + FormBuilder.GetCSSRule('font-weight', values.ButtonFontWeight) 32539 + FormBuilder.GetCSSRule('height', values.ButtonHeight) 32540 + FormBuilder.GetCSSRule('width', values.ButtonWidth) 32541 + FormBuilder.GetCSSRule('margin', values.ButtonMargin) 32542 + FormBuilder.GetCSSRule('padding', values.ButtonPadding) 32543 + FormBuilder.GetCSSRule('border', values.ButtonBorder) 32544 + FormBuilder.GetCSSRule('border-radius', values.ButtonBorderRadius) 32545 + '}'; 32546 32547 html += "</style>"; 32548 32549 return html; 32550 }; 32551 32552 FormBuilder.GetCSSRule = function (rule, value) { 32553 return rule + ':' + value + ';'; 32554 }; 32555 32556 FormBuilder.GetColumnMarkup = function (column, contentID) { 32557 var className = FormBuilder.GetBootsrapColumnClassName(column.width); 32558 var html = '<div class="' + className + '">' 32559 32560 html += FormBuilder.GetFieldTypeMarkup(column.fieldType, contentID); 32561 32562 html += '</div>'; 32563 32564 return html; 32565 } 32566 32567 FormBuilder.GetFieldTypeMarkup = function (fieldType, contentID) { 32568 var html = ''; 32569 32570 if (fieldType.DataType !== Agility.UGC.API.DataType.Boolean) { 32571 html = FormBuilder.GetLabelMarkup(fieldType, contentID); 32572 } 32573 32574 var basicFieldConfig = FormBuilder.GetBasicFieldConfig(fieldType, contentID); 32575 32576 switch (fieldType.DataType) { 32577 case Agility.UGC.API.DataType.String: 32578 html += FormBuilder.GetStringFieldTypeMarkup(fieldType, contentID, basicFieldConfig); 32579 break; 32580 case Agility.UGC.API.DataType.TextBlob: 32581 case Agility.UGC.API.DataType.HTML: 32582 html += FormBuilder.GetTextAreaFieldTypeMarkup(fieldType, contentID, basicFieldConfig); 32583 break; 32584 case Agility.UGC.API.DataType.Int: 32585 html += FormBuilder.GetIntFieldTypeMarkup(fieldType, contentID, basicFieldConfig); 32586 break; 32587 case Agility.UGC.API.DataType.Double: 32588 html += FormBuilder.GetDoubleFieldTypeMarkup(fieldType, contentID, basicFieldConfig); 32589 break; 32590 case Agility.UGC.API.DataType.DateTime: 32591 html += FormBuilder.GetDateTimeFieldTypeMarkup(fieldType, contentID, basicFieldConfig); 32592 break; 32593 case Agility.UGC.API.DataType.Email: 32594 html += FormBuilder.GetEmailFieldTypeMarkup(fieldType, contentID, basicFieldConfig); 32595 break; 32596 case Agility.UGC.API.DataType.Boolean: 32597 html += FormBuilder.GetBooleanFieldTypeMarkup(fieldType, contentID, basicFieldConfig); 32598 break; 32599 case Agility.UGC.API.DataType.Dropdown: 32600 html += FormBuilder.GetDropdownFieldTypeMarkup(fieldType, contentID, basicFieldConfig); 32601 break; 32602 case Agility.UGC.API.DataType.File: 32603 html += FormBuilder.GetFileFieldTypeMarkup(fieldType, contentID, basicFieldConfig); 32604 break; 32605 default: 32606 } 32607 32608 return html; 32609 }; 32610 32611 FormBuilder.GetStringFieldTypeMarkup = function (fieldType, contentID, fieldConfig) { 32612 return '<input type="text"' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.placeholder + fieldConfig.required + ' data-parsley-trigger="keyup"/>' + fieldConfig.description; 32613 }; 32614 32615 FormBuilder.GetTextAreaFieldTypeMarkup = function (fieldType, contentID, fieldConfig) { 32616 return '<textarea' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.placeholder + fieldConfig.required + ' data-parsley-trigger="keyup"></textarea>' + fieldConfig.description; 32617 }; 32618 32619 FormBuilder.GetIntFieldTypeMarkup = function (fieldType, contentID, fieldConfig) { 32620 return '<input type="text"' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.placeholder + fieldConfig.required + ' data-parsley-type="digits" max="2147483647" data-parsley-trigger="keyup"/>' + fieldConfig.description; 32621 }; 32622 32623 FormBuilder.GetDoubleFieldTypeMarkup = function (fieldType, contentID, fieldConfig) { 32624 return '<input type="text"' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.placeholder + fieldConfig.required + ' data-parsley-type="number" data-parsley-trigger="keyup"/>' + fieldConfig.description; 32625 }; 32626 32627 FormBuilder.GetDateTimeFieldTypeMarkup = function (fieldType, contentID, fieldConfig) { 32628 return '<input type="date"' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.placeholder + fieldConfig.required + ' data-date-format="YYYY-MM-DD" data-parsley-trigger="keyup"/>' + fieldConfig.description; 32629 }; 32630 32631 FormBuilder.GetEmailFieldTypeMarkup = function (fieldType, contentID, fieldConfig) { 32632 return '<input type="email"' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.placeholder + fieldConfig.required + ' data-date-format="YYYY-MM-DD" data-parsley-trigger="keyup"/>' + fieldConfig.description; 32633 }; 32634 32635 FormBuilder.GetBooleanFieldTypeMarkup = function (fieldType, contentID, fieldConfig) { 32636 var html = '<label id="agility-form-checkbox-label-' + fieldType.Name + '-' + contentID + '" class="agility-form-checkbox-label" for="' + fieldType.Name + '-' + contentID + '">'; 32637 32638 html += '<input type="checkbox"' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.required + '/>'; 32639 32640 html += '<span>' + fieldType.Label + '</span></label> '; 32641 32642 return html; 32643 }; 32644 32645 FormBuilder.GetDropdownFieldTypeMarkup = function (fieldType, contentId, fieldConfig) { 32646 var html = '<select ' + fieldConfig.id + fieldConfig.name + fieldConfig.value + fieldConfig.required + '>'; 32647 32648 html += '<option>' + fieldConfig.optionLabel + '</option>'; 32649 32650 var options = []; 32651 32652 if (fieldType.AdditionalMetaData) { 32653 options = fieldType.AdditionalMetaData.split('\n'); 32654 32655 for (var i = 0; i < options.length; i++) { 32656 var option = options[i]; 32657 32658 var text = option.split('|')[0]; 32659 var value = option.split('|')[1]; 32660 32661 html += '<option value="' + value + '">
32661' + text + '</option>'; 32662 } 32663 } 32664 32665 html += '</select>'; 32666 32667 html += fieldConfig.description; 32668 32669 return html; 32670 }; 32671 32672 FormBuilder.GetFileFieldTypeMarkup = function (fieldType, contentID, fieldConfig) { 32673 return '<input type="file"' + fieldConfig.id + fieldConfig.name + fieldConfig.required + '/>' + fieldConfig.description; 32674 }; 32675 32676 FormBuilder.GetBasicFieldConfig = function (fieldType, contentID) { 32677 var value = fieldType.DefaultValue ? ' value="' + fieldType.DefaultValue + '" ' : ''; 32678 var name = ' name="' + fieldType.Name + '" '; 32679 var required = fieldType.Required ? ' data-parsley-required="true" ' : ''; 32680 var id = ' id="' + fieldType.Name + '-' + contentID + '" '; 32681 var description = fieldType.JSONFields.Description ? '<small class="agility-form-field-description">' + fieldType.JSONFields.Description + '</small>' : ''; 32682 var placeholder = fieldType.JSONFields.PlaceholderText ? ' placeholder="' + fieldType.JSONFields.PlaceholderText + '" ' : ''; 32683 var optionLabel = fieldType.JSONFields.PlaceholderText ? fieldType.JSONFields.PlaceholderText : ''; 32684 32685 return { 32686 value: value, 32687 name: name, 32688 required: required, 32689 id: id, 32690 description: description, 32691 placeholder: placeholder, 32692 optionLabel: optionLabel 32693 } 32694 }; 32695 32696 FormBuilder.GetLabelMarkup = function (fieldType, contentID) { 32697 var forID = ' for="' + fieldType.Name + '-' + contentID + '">'; 32698 return '<label' + forID + fieldType.Label + '</label>'; 32699 }; 32700 32701 FormBuilder.GetBootsrapColumnClassName = function (width) { 32702 var className = 'agility-form-col-full'; 32703 32704 switch (width) { 32705 case 'quarter': 32706 className = 'agility-form-col-quarter'; 32707 break; 32708 case 'third': 32709 className = 'agility-form-col-third'; 32710 break; 32711 case 'half': 32712 className = 'agility-form-col-half'; 32713 break; 32714 case 'full': 32715 className = 'agility-form-col-full'; 32716 break; 32717 default: 32718 className = 'agility-form-col-full'; 32719 } 32720 32721 return className; 32722 }; 32723 32724 FormBuilder.GetColumnWidth = function (widthStr) { 32725 var width = 0; 32726 32727 switch (widthStr) { 32728 case 'quarter': 32729 width = 0.25; 32730 break; 32731 case 'third': 32732 width = 0.33; 32733 break; 32734 case 'half': 32735 width = 0.5; 32736 break; 32737 case 'full': 32738 width = 1; 32739 break; 32740 default: 32741 width = 1; 32742 } 32743 32744 return width; 32745 }; 32746 32747 FormBuilder.GetSubmitButtonMarkup = function (label, formSelector, contentID, languageCode, mode, recordTypeID) { 32748 var html = '<div class="agility-form-row"><div class="agility-form-col-full"><button id="agility-form-' + contentID + '-submit-btn" class="agility-form-submit-btn" type="button" onclick="Agility.FormBuilder.ValidateAndSubmitForm(\'' + formSelector + '\',' + contentID + ',\'' + languageCode + '\',' + mode + ',' + recordTypeID + ')">' + label + '</button></div></div>'; 32749 32750 return html; 32751 }; 32752 32753 FormBuilder.ValidateAndSubmitForm = function (formSelector, contentID, languageCode, mode, recordTypeID) { 32754 var formElement = $(formSelector); 32755 32756 //disable all inputs in form 32757 $('input, select, button, textarea', formElement).each(function () { 32758 $(this).attr('disabled', true); 32759 }); 32760 32761 formElement.addClass('submitting'); 32762 32763 if (formElement.parsley().validate()) { 32764 var data = { 32765 ContentID: contentID, 32766 LanguageCode: languageCode, 32767 Mode: mode, 32768 RecordTypeID: recordTypeID, 32769 Values: {} 32770 }; 32771 32772 var values = {}; 32773 $('input, select, textarea', formElement).each(function () { 32774 var $elem = $(this); 32775 var value = $elem.val(); 32776 32777 if ($elem.attr("type") == "checkbox") { 32778 value = $elem.prop("checked"); 32779 } 32780 32781 values[this.name] = value; 32782 }); 32783 32784 data.Values = values; 32785 32786 //form is valid check if there are any files to be uploaded 32787 var fileInputs = $('input[type="file"]', formElement); 32788 32789 if (fileInputs.length > 0) { 32790 var filesToUpload = 0; 32791 var filesUploaded = 0; 32792 32793 for (var i = 0; i < fileInputs.length; i++) { 32794 var fileInput = fileInputs[i]; 32795 if ($(fileInput).val()) { 32796 filesToUpload++; 32797 } 32798 } 32799 32800 if (filesToUpload === 0) { 32801 _submitAndUpdateUI(data, formElement); 32802 } else { 32803 var fileInputNameValuePairs = []; 32804 for (var i = 0; i < fileInputs.length; i++) { 32805 var fileInput = fileInputs[i]; 32806 32807 if ($(fileInput).val()) { 32808 _uploadFile(fileInput, 32809 function (resp) { 32810 //success 32811 if (resp && resp.ResponseType === Agility.UGC.API.ResponseType.Error) { 32812 return; 32813 } 32814 32815 filesUploaded++; 32816 fileInputNameValuePairs.push({ name: this.fileInput.name, value: resp }); 32817 32818 if (filesToUpload === filesUploaded) { 32819 for (var i = 0; i < fileInputNameValuePairs.length; i++) { 32820 var fileInputNameValuePair = fileInputNameValuePairs[i]; 32821 this.data.Values[fileInputNameValuePair.name] = fileInputNameValuePair.value; 32822 } 32823 32824 _submitAndUpdateUI(this.data, this.formElement); 32825 } 32826 }.bind({ fileInput: fileInput, data: data, formElement: formElement }), 32827 function (err) { 32828 //err 32829 if (console) console.log(err); 32830 }, function () { 32831 //always 32832 $(this.fileInput).removeClass('uploading'); 32833 $(this.formElement).removeClass('uploading'); 32834 }.bind({ fileInput: fileInput, formElement: formElement}), function (progress) { 32835 //progress 32836 $(this.fileInput).addClass('uploading'); 32837 $(this.formElement).addClass('uploading'); 32838 32839 if (console) console.log("upload progress", progress); 32840 }.bind({ fileInput: fileInput, formElement: formElement }) 32841 ); 32842 } 32843 } 32844 } 32845 32846 32847 } else { 32848 //no need to upload anything, submit it 32849 _submitAndUpdateUI(data, formElement); 32850 } 32851 32852 } else { 32853 $('input, select, button, textarea', formElement).each(function () { 32854 $(this).removeAttr('disabled'); 32855 }); 32856 32857 formElement.removeClass('submitting'); 32858 } 32859 } 32860 32861 function _submitAndUpdateUI(data, formElement) { 32862 FormBuilder.Submit(data, function (response) { 32863 var contentID = formElement.data('agility-form-content-id'); 32864 32865 var htmlContainerID = 'agility-form-' + contentID; 32866 var htmlContainer = $('#' + htmlContainerID); 32867 var outerHeight = formElement.outerHeight(); 32868 32869 var contentItemValues = window.FormBuilderValues[htmlContainerID]; 32870 32871 if (!contentItemValues) { 32872 //calling from content manager 32873 htmlContainerID = window.FormBuilderContainerName; 32874 htmlContainer = $('#' + htmlContainerID); 32875 contentItemValues = window.FormBuilderValues[window.FormBuilderContainerName]; 32876 } 32877 32878 formElement.hide(); 32879 32880 if (response.ResponseType != Agility.UGC.API.ResponseType.OK) { 32881 htmlContainer.append('<div id="agility-form-msg">' + contentItemValues.ErrorCopy + '</div>'); 32882 } else { 32883 htmlContainer.append('<div id="agility-form-msg">' + contentItemValues.SuccessCopy + '</div>'); 32884 } 32885 32886 document.getElementById("agility-form-msg").scrollIntoView(); 32887 32888 }); 32889 32890 } 32891 32892 FormBuilder.Submit = function (data, callback) { 32893 if (!checkApiIntialized(callback)) return; 32894
32895 var postData = Agility.JSON.encode(data); 32896 32897 _performPost('SaveFormPost', { postData: postData }, callback); 32898 }; 32899 32900 function _performPost(methodName, postData, callback) { 32901 32902 if (!postData) postData = {}; 32903 32904 var url = Agility.UGC.API.APIUrl; 32905 if (url == '' || url == null) return null; 32906 32907 url = url.toLowerCase(); 32908 32909 url = url.replace("http://", "https://"); 32910 url = url.replace("/agility-ugc-api-jsonp.svc", "/ugc-api"); 32911 32912 if (url.lastIndexOf('/') != url.length - 1) url += '/'; 32913 32914 //create the base url for the call 32915 url += methodName; 32916 32917 //sanitize the post data 32918 if (postData.postData) { 32919 var postDataStr = postData.postData; 32920 32921 postData.postData = '__SANITIZED__' + postDataStr 32922 .replace(/&/g, '&') 32923 .replace(/'/g, ''') 32924 .replace(/</g, '<') 32925 .replace(/>/g, '>'); 32926 } 32927 32928 //add the auth stuff into the postData 32929 postData.accessKey = Agility.UGC.API.APIAccessKey; 32930 postData.seconds = Agility.UGC.API.APISeconds; 32931 postData.randomNumber = Agility.UGC.API.APIRandomNumber; 32932 postData.hash = Agility.UGC.API.APIHash; 32933 postData.profileRecordID = Agility.UGC.API.APIProfileRecordID; 32934 32935 return $.ajax(url, { 32936 type: 'POST', 32937 data: postData, 32938 dataType: 'json', 32939 xhrFields: { 32940 withCredentials: true 32941 }, 32942 crossDomain: true 32943 }).done(function (result) { 32944 callback(result); 32945 }).fail(function (err, status, errorMessage) { 32946 32947 if (status == 'abort') { 32948 //do nothing... 32949 return; 32950 } 32951 32952 callback({ 32953 ResponseType: Agility.UGC.API.ResponseType.Error, 32954 Message: errorMessage 32955 }); 32956 }); 32957 }; 32958 32959 function checkApiIntialized(callback) { 32960 32961 if (Agility.UGC.API.APIUrl == null || Agility.UGC.API.APIUrl == '' || Agility.UGC.API.APIAccessKey == undefined) { 32962 callback({ 32963 ResponseType: Agility.UGC.API.ResponseType.Error, 32964 Message: 'The Agility UGC API has not been initialized.', 32965 ResponseData: null 32966 }); 32967 32968 return false; 32969 } 32970 32971 return true; 32972 }; 32973 32974 function _uploadFile(fileInputElem, callback, errorCallback, alwaysCallback, progressCallback) { 32975 32976 //TODO: check for files... 32977 32978 var fileToUpload = fileInputElem.files[0] 32979 var fileSize = fileToUpload.size; 32980 var fileName = fileToUpload.name; 32981 32982 32983 32984 var methodName = "Upload"; 32985 var url = Agility.UGC.API.APIUrl; 32986 if (url == "" || url == null) return null; 32987 url = url.toLowerCase(); 32988 32989 url = url.replace("http://", "https://"); 32990 url = url.replace("/agility-ugc-api-jsonp.svc", "/ugc-api"); 32991 32992 if (url.lastIndexOf("/") != url.length - 1) url += "/"; 32993 32994 //create the base url for the call 32995 url += methodName; 32996 32997 if (url.indexOf("/") == 0) url = getBaseUrl() + url; 32998 32999 //add the auth stuff into the postData 33000 var formData = new FormData(); 33001 formData.append("file", fileToUpload); 33002 formData.append("fileName", fileName); 33003 formData.append("accessKey", Agility.UGC.API.APIAccessKey); 33004 formData.append("seconds", Agility.UGC.API.APISeconds); 33005 formData.append("randomNumber", Agility.UGC.API.APIRandomNumber); 33006 formData.append("hash", Agility.UGC.API.APIHash); 33007 formData.append("profileRecordID", Agility.UGC.API.APIProfileRecordID); 33008 33009 return $.ajax({ 33010 url: url, 33011 xhr: function () { // Custom XMLHttpRequest 33012 var myXhr = $.ajaxSettings.xhr(); 33013 if (myXhr.upload) { // Check if upload property exists 33014 if ($.isFunction(progressCallback)) { 33015 myXhr.upload.addEventListener('progress', progressCallback, false); 33016 } 33017 } 33018 return myXhr; 33019 }, 33020 type: 'POST', 33021 data: formData, 33022 processData: false, 33023 contentType: false, 33024 xhrFields: { 33025 withCredentials: true 33026 }, 33027 crossDomain: true 33028 }).done(function (result) { 33029 33030 if (result.IsError) { 33031 if (errorCallback != undefined && $.isFunction(errorCallback)) { 33032 errorCallback(result.ErrorMessage); 33033 } 33034 33035 } else { 33036 //redirect to the return url 33037 if (result.ResponseData) { 33038 callback(result.ResponseData); 33039 } else { 33040 callback(result); 33041 } 33042 } 33043 33044 }).fail(function (err, status, errorMessage) { 33045 33046 if (status == "abort") { 33047 //do nothing... 33048 return; 33049 } 33050 33051 if (errorCallback != undefined && $.isFunction(errorCallback)) { 33052 errorCallback(errorMessage, status); 33053 } 33054 33055 }).always(function () { 33056 if (alwaysCallback != undefined && $.isFunction(alwaysCallback)) { 33057 alwaysCallback(); 33058 } 33059 }); 33060 } 33061 33062 33063})(Agility.FormBuilder);; 33064/// <reference path="Agility.js" /> 33065 33066Agility.RegisterNamespace("Agility.UGC.API"); 33067 33068(function (API) { 33069 33070 //ENUMS 33071 API.DataType = { 33072 String: 0, 33073 TextBlob: 1, 33074 Int: 2, 33075 Double: 3, 33076 DateTime: 4, 33077 File: 5, 33078 GUID: 6, 33079 Encrypted: 7, 33080 Hashed: 8, 33081 Boolean: 9, 33082 Dropdown: 10, 33083 HTML: 11, 33084 Email: 12 33085 } 33086 33087 API.RecordState = { 33088 New: 0, 33089 Published: 1, 33090 Deleted: 2, 33091 Processing: 3, 33092 Declined: 4, 33093 Error: 5, 33094 Escalated: 6, 33095 AwaitingReview: 7, 33096 Draft: 8, 33097 All: -1 33098 } 33099 33100 API.Permission = { 33101 Read: 0, 33102 Create: 1, 33103 Edit: 2, 33104 Delete: 3, 33105 Moderate: 4, 33106 Administer: 5 33107 } 33108 33109 API.FileStorage = { 33110 RelativeURL: 0, 33111 BaseURL: 1, 33112 EdgeURL: 2 33113 } 33114 33115 API.SortDirection = { 33116 ASC: "ASC", 33117 DESC: "DESC" 33118 } 33119 33120 API.ResponseType = { 33121 OK: 0, 33122 Error: 1 33123 } 33124 33125 API.FileService = { 33126 AmazonS3: 0, 33127 YouTube: 1, 33128 Flickr: 2, 33129 Image: 3, 33130 Video: 4, 33131 Ooyala: 5, 33132 Brightcove: 6 33133 } 33134 33135 API.FileServiceState = { 33136 New: 0, 33137 Unprocessed: 1, 33138 Processed: 2, 33139 Error: 3 33140 } 33141 33142 API.RecordFlag = { 33143 Spam: "Spam", 33144 Flagged: "Flagged", 33145 Illegal: "Illegal", 33146 Abuse: "Abuse" 33147 } 33148 33149 API.AggregateTypes = { 33150 Count: 0, 33151 Sum: 1, 33152 Average: 2 33153 } 33154 33155 API.FeedbackContentType = { 33156 WCM: 0, 33157 UGC: 1, 33158 Custom: 2 33159 } 33160 33161 API.FeedbackSubmissionType = { 33162 Like: 0, 33163 Rating: 1, 33164 Vote: 2, 33165 ApproveDisapprove: 3, 33166 Custom: 4 33167 } 33168 33169 API.SubmissionInterval = { 33170 None: -1, 33171 Day: 0, 33172 Hour: 1, 33173 Week: 2, 33174 Month: 3, 33175 Minute: 4, 33176 SingleSubmissionOnly: 5 33177 } 33178 33179 33180 API.FileServiceMetaDataTypeName = "JSONPFileServiceMetaData:#Agility.UGC.API.ServiceObjects"; 33181 33182 API.YouTubeMetaField = { 33183 OriginalFilePath: "OriginalFilePath", 33184 VideoID: "VideoID", 33185 Description: "Description", 33186 Category: "Category", 33187 Title: "Title", 33188 Keywords: "Keywords", 33189 Private: "Private", 33190 YouTubeState: "YouTubeState", 33191 Duration: "Duration" 33192 }; 33193 33194 //from here: http://www.flickr.com/services/api/upload.api.html 33195 33196 API.FlickrMetaField = { 33197 OriginalFilePath: "OriginalFilePath", 33198 title: "title", 33199 description: "description", 33200 tags: "tags", 33201 is_public: "is_public", 33202 is_friend: "is_friend",
33203 is_family: "is_family", 33204 safety_level: "safety_level", 33205 hidden: "hidden", 33206 photo_id: "photo_id" 33207 33208 //other values are also appended as they are made available 33209 /* 33210 secret 33211 photopage 33212 SquareImageUrl 33213 ThumbnailImageUrl 33214 SmallImageUrl 33215 MediumImageUrl 33216 LargeImageUrl 33217 */ 33218 }; 33219 33220 API.OoyalaMetaField = { 33221 embedCode: "embedCode", 33222 title: "title", 33223 description: "description", 33224 status: "status" 33225 33226 //http://www.ooyala.com/support/docs/backlot_api#query 33227 //other metadata (plus any "generic" metadata) values are also appended as they are made available 33228 /* 33229 thumbnailUrl 33230 hostedAt 33231 content_type 33232 uploadedAt 33233 length 33234 size 33235 updatedAt 33236 width 33237 height 33238 */ 33239 }; 33240 33241 API.SearchArg = function () { 33242 /// <summary> 33243 /// The search object for the SearchRecords method. 33244 /// </summary> 33245 ///<field name="PageSize" Type="Number">The number of records per page.</field> 33246 ///<field name="RecordOffset" Type="Number"></field> 33247 ///<field name="IncludeSpam" Type="Boolean"></field> 33248 ///<field name="IncludeFlagged" Type="Boolean"></field> 33249 ///<field name="IncludeIllegal" Type="Boolean"></field> 33250 ///<field name="State" Type="API.RecordState"></field> 33251 ///<field name="SortedField" Type="String"></field> 33252 ///<field name="SortDirection" Type="String"></field> 33253 ///<field name="RecordTypeName" Type="String"></field> 33254 ///<field name="Search" Type="String">The search string.</field> 33255 ///<field name="CacheKey" Type="String">A custom cache key that will be used instead of the record type id to cache the results with.</field> 33256 ///<field name="Columns" Type="Array">A list of the field names that you want to be returned.</field> 33257 33258 PageSize = 20; 33259 RecordOffset = 0; 33260 IncludeSpam = false; 33261 IncludeFlagged = false; 33262 IncludeIllegal = false; 33263 State = API.RecordState.Published; 33264 SortedField = ""; 33265 SortDirection = ""; 33266 RecordTypeName = null; 33267 Search = ""; 33268 CacheKey = null; 33269 Columns = []; 33270 FileStorage = API.FileStorage.RelativeURL; 33271 IncludeStatistics = false; 33272 } 33273 33274 API.CommentSearchArg = function () { 33275 /// <summary> 33276 /// The search object for the SearchComments method. 33277 /// </summary> 33278 ///<field name="RelatedContentID" Type="Number">The ID of the Related Content Item</field> 33279 ///<field name="PageSize" Type="Number">The number of records per page.</field> 33280 ///<field name="RecordOffset" Type="Number"></field> 33281 ///<field name="SortedField" Type="String"></field> 33282 ///<field name="SortDirection" Type="String"></field> 33283 ///<field name="RecordTypeName" Type="String"></field> 33284 ///<field name="CacheKey" Type="String">A custom cache key that will be used instead of the record type id to cache the results with.</field> 33285 ///<field name="OtherStates" Type="Array"></field> 33286 ///<field name="State" Type="API.RecordState"></field> 33287 ///<field name="FileStorage" Type="API.FileStorage"></field> 33288 ///<field name="Columns" Type="Array">A list of the field names that you want to be returned.</field> 33289 33290 33291 RelatedContentID: -1; 33292 PageSize: 20; 33293 RecordOffset: 0; 33294 SortedField: "CreatedOn"; 33295 SortDirection: "DESC"; 33296 RecordTypeName: ""; 33297 CacheKey = null; 33298 OtherStates = []; 33299 State = API.RecordState.Published; 33300 FileStorage = API.FileStorage.RelativeURL; 33301 Columns = []; 33302 IgnoreAbuse = true; 33303 IncludeFlagged = false; 33304 IncludeIllegal = false; 33305 33306 } 33307 33308 API.FeedbackSearchArg = function () { 33309 /// <summary> 33310 /// The search object for the GetFeedbackAggregate method. 33311 /// </summary> 33312 ///<field name="ReferenceName" Type="String">The Reference name of the list the feedback refers to</field> 33313 ///<field name="FeedbackContentType" Type="FeedbackContentType">The content type the reference name refers to (WCM/UGC/Custom)</field> 33314 ///<field name="FeedbackSubmissionType" Type="FeedbackSubmissionType">The submission type the reference name refers to (Like/Vote/Rating/ApproveDisaprove/Custom)</field> 33315 ///<field name="RelatedContentID" Type="int">The ID the item is related to</field> 33316 ///<field name="StartDate" Type="Date"></field> 33317 ///<field name="EndDate" Type="Date"></field> 33318 ///<field name="IsPositive" Type="Boolean"></field> 33319 ///<field name="Action" Type="AggregateTypes">The action to perform (Count/Sum/Average)</field> 33320 33321 ReferenceName = null; 33322 ContentType = -1; 33323 SubmissionType = -1; 33324 RelatedContentIDs = new Array(); 33325 StartDate = null; 33326 EndDate = null; 33327 IsPositive = null; 33328 Action = null; 33329 33330 } 33331 33332 33333 API.BooleanFeedback = function () { 33334 BooleanFeedbackID = -1; 33335 FeedbackTypeID = -1; 33336 RelatedContentID = -1; 33337 ProfileRecordID = -1; 33338 ExternalProfileID = null; 33339 CreatedOn = null; 33340 IsPositive = null; 33341 33342 ReferenceName = null; 33343 ContentType = -1; 33344 SubmissionType = -1; 33345 33346 //Submission Rules 33347 RequiresAuthentication = false; 33348 SubmissionIntervalUnit = API.SubmissionInterval.None; 33349 SubmissionIntervalValue = 1; 33350 } 33351 33352 API.RatingFeedback = function () { 33353 RatingFeedbackID = -1; 33354 FeedbackTypeID = -1; 33355 RelatedContentID = -1; 33356 ProfileRecordID = -1; 33357 ExternalProfileID = null; 33358 CreatedOn = null; 33359 IsPositive = null; 33360 RatingValue = 0; 33361 33362 ReferenceName = null; 33363 ContentType = -1; 33364 SubmissionType = -1; 33365 33366 //Submission Rules 33367 RequiresAuthentication = false; 33368 SubmissionIntervalUnit = API.SubmissionInterval.None; 33369 SubmissionIntervalValue = 1; 33370 } 33371 33372 API.Record = function () { 33373 var ID = -1; 33374 var RecordTypeName; 33375 var CreatedOn; 33376 var ModifiedOn; 33377 } 33378 33379 API.Initialized = false; 33380 33381 API.APIUrl = ""; 33382 33383 API.OnInit = function (API_Url, API_AccessKey, API_Seconds, API_RandomNumber, API_ProfileRecordID, API_Hash) { 33384 /// <summary> 33385 /// Initialize the Agility DataService API 33386 /// </summary> 33387 /// <param name="API_Url" type="String">The URL to the Agility DataService REST API.</param> 33388 /// <param name="API_AccessKey" type="String">The API Key.</param> 33389 /// <param name="API_Seconds" type="String">The # of Seconds.</param> 33390 /// <param name="API_RandomNumber" type="String">A Random number.</param> 33391 /// <param name="API_ProfileRecordID" type="String">The current user ID.</param> 33392 /// <param name="API_Hash" type="String">The API Hash.</param> 33393 33394 if (API_Url != undefined && API_Url != null) { 33395 API.APIUrl = API_Url; 33396 }
33397 API.APIAccessKey = API_AccessKey; 33398 API.APISeconds = API_Seconds; 33399 API.APIRandomNumber = API_RandomNumber; 33400 API.APIProfileRecordID = API_ProfileRecordID; 33401 API.APIHash = API_Hash; 33402 API.Initialized = true; 33403 33404 } 33405 33406 33407 function checkApiIntialized(callback) { 33408 33409 if (API.APIUrl == null || API.APIUrl == "" || API.APIAccessKey == undefined) { 33410 callback({ 33411 ResponseType: API.ResponseType.Error, 33412 Message: "The Agility UGC API has not been initialized.", 33413 ResponseData: null 33414 }); 33415 33416 return false; 33417 } 33418 33419 return true; 33420 } 33421 33422 33423 33424 API.GetAllRecordTypes = function (callback) { 33425 /// <summary> 33426 /// Get All Record Types. 33427 /// </summary> 33428 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33429 33430 if (!checkApiIntialized(callback)) return; 33431 var url = _buildAPIUrl("GetAllRecordTypes", null); 33432 33433 33434 33435 jQuery.getJSON(url, callback); 33436 33437 } 33438 33439 API.GetRecordType = function (recordTypeID, callback) { 33440 /// <summary> 33441 /// Get a record based on the record type id. 33442 /// </summary> 33443 /// <param name="recordTypeID">The ID of the record type to return.</param> 33444 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33445 if (!checkApiIntialized(callback)) return; 33446 var url = _buildAPIUrl("GetRecordType", [recordTypeID]); 33447 33448 jQuery.getJSON(url, callback); 33449 33450 } 33451 33452 API.GetRecordTypeByName = function (recordTypeName, callback) { 33453 /// <summary> 33454 /// Get a record based on the record type name. 33455 /// </summary> 33456 /// <param name="recordTypeName">The name of the record type to return.</param> 33457 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33458 if (!checkApiIntialized(callback)) return; 33459 33460 var url = _buildAPIUrl("GetRecordTypeByName", [recordTypeName]); 33461 jQuery.getJSON(url, callback); 33462 } 33463 33464 API.SaveRecordType = function (recordType, callback) { 33465 /// <summary> 33466 /// Saves a record type. 33467 /// </summary> 33468 /// <param name="recordType">The record type to save.</param> 33469 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33470 33471 if (!checkApiIntialized(callback)) return; 33472 var postData = Agility.JSON.encode(recordType); 33473 33474 var url = _buildAPIUrl("SaveRecordType", null); 33475 33476 _submitPostData(url, postData, callback); 33477 33478 } 33479 33480 API.DeleteRecordType = function (recordTypeID, callback) { 33481 /// <summary> 33482 /// Get All Record Types. 33483 /// </summary> 33484 /// <param name="recordTypeID">The ID of the record type to return.</param> 33485 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33486 33487 if (!checkApiIntialized(callback)) return; 33488 33489 var url = _buildAPIUrl("DeleteRecordType", [recordTypeID]); 33490 33491 jQuery.getJSON(url, callback); 33492 33493 } 33494 33495 API.GetRecord = function (recordID, fileStorage, callback) { 33496 /// <summary> 33497 /// Gets a Record. 33498 /// </summary> 33499 /// <param name="recordID" type="Number">The ID of the record to return.</param> 33500 /// <param name="RelativeURL" type="Agility.UGC.API.FileStorage">(optional) The method to be used for building file field URLs that may be on this document.</param> 33501 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33502 33503 if ($.isFunction(fileStorage)) { 33504 callback = fileStorage; 33505 fileStorage = null; 33506 33507 } 33508 33509 if (!checkApiIntialized(callback)) return; 33510 33511 var url = null; 33512 if (fileStorage == null) { 33513 url = _buildAPIUrl("GetRecord", [recordID]); 33514 } else { 33515 url = _buildAPIUrl("GetRecord", [recordID], "fileStorage=" + escape(fileStorage)); 33516 } 33517 33518 jQuery.getJSON(url, callback); 33519 33520 } 33521 33522 API.GetRecordHistory = function (recordID, callback) { 33523 /// <summary> 33524 /// Gets a the Version Histor for a Record. This method requires admin access. 33525 /// </summary> 33526 /// <param name="recordID">The ID of the record to return.</param> 33527 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33528 33529 if (!checkApiIntialized(callback)) return; 33530 33531 var url = _buildAPIUrl("GetRecordHistory", [recordID]); 33532 33533 jQuery.getJSON(url, callback); 33534 33535 } 33536 33537 33538 33539 API.DeleteRecord = function (recordID, callback) { 33540 /// <summary> 33541 /// Deletes a Record. 33542 /// </summary> 33543 /// <param name="recordID">The ID of the record to return.</param> 33544 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33545 33546 if (!checkApiIntialized(callback)) return; 33547 33548 var url = _buildAPIUrl("DeleteRecord", [recordID]); 33549 33550 jQuery.getJSON(url, callback); 33551 33552 } 33553 33554 33555 API.SetRecordFlag = function (recordID, flag, reason, callback) { 33556 /// <summary> 33557 /// Sets whether a record is flagged or not. 33558 /// </summary> 33559 /// <param name="recordID" type="Number">The ID of the record to return.</param> 33560 /// <param name="flag" type="Agility.UGC.API.RecordFlag">
33560Whether the record is flagged or not.</param> 33561 /// <param name="reason" type="String">Whether the record is flagged or not.</param> 33562 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33563 33564 if (!checkApiIntialized(callback)) return; 33565 33566 var query = null; 33567 if (reason != null && reason != "") { 33568 query = "reason=" + escape(reason); 33569 } 33570 33571 var url = _buildAPIUrl("SetRecordFlag", [recordID, flag], query); 33572 33573 jQuery.getJSON(url, callback); 33574 33575 } 33576 33577 33578 API.InsertRecordHistory = function (recordID, comment, callback) { 33579 /// <summary> 33580 /// Adds a comment to the record history. 33581 /// </summary> 33582 /// <param name="recordID">The ID of the record to return.</param> 33583 /// <param name="comment">The comment.</param> 33584 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33585 33586 if (!checkApiIntialized(callback)) return; 33587 33588 var postData = comment; 33589 33590 var url = _buildAPIUrl("InsertRecordHistory", [recordID]); 33591 33592 _submitPostData(url, postData, callback); 33593 33594 33595 } 33596 33597 API.SetRecordState = function (recordID, recordState, reason, comment, callback) { 33598 /// <summary> 33599 /// Sets a record state. Used for publish/decline, etc. 33600 /// </summary> 33601 /// <param name="recordID">The ID of the record to return.</param> 33602 /// <param name="recordState">The State of the record (from enum)</param> 33603 /// <param name="reason">The reason that the record is in this state. May be null if not an Error state.</param> 33604 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33605 /// <param name="comment">The comment to send to the user with any notification, if any.</param> 33606 33607 if ($.isFunction(comment)) { 33608 callback = comment; 33609 comment = ""; 33610 } 33611 33612 if (!checkApiIntialized(callback)) return; 33613 33614 //note - this method has been changed to a POST so that the reason can be as long as needed. 33615 if (reason == undefined || reason == null) reason = ""; 33616 if (comment == undefined || comment == null) comment = ""; 33617 33618 var postData = { reason: reason, comment: comment }; 33619 33620 33621 var url = _buildAPIUrl("SetRecordStateEx", [recordID, recordState]); 33622 33623 _submitPostData(url, postData, callback); 33624 33625 } 33626 33627 API.SetRecordFileState = function (recordID, fieldName, fileServiceState, callback) { 33628 /// <summary> 33629 /// Sets the file service state on a given file service field. 33630 /// </summary> 33631 /// <param name="recordID">The ID of the record to return.</param> 33632 /// <param name="fieldName">The name of the field the file is associated with on the record.</param> 33633 /// <param name="fileServiceState">The fileServiceState to set the field to. Normally this will be FileServiceState.Unprocessed.</param> 33634 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33635 33636 if (!checkApiIntialized(callback)) return; 33637 33638 var url = _buildAPIUrl("SetRecordFileState", [recordID, fieldName, fileServiceState]); 33639 33640 jQuery.getJSON(url, callback); 33641 } 33642 33643 API.UpdateRecordTypeAlert = function (recordTypeID, recordState, moderatorID, otherNotificationType, callback) { 33644 /// <summary> 33645 /// Inserts or updates a RecordTypeAlert. 33646 /// </summary> 33647 /// <param name="recordTypeID"></param> 33648 /// <param name="recordState"></param> 33649 /// <param name="moderatorID"></param> 33650 /// <param name="otherNotificationType"></param> 33651 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33652 33653 if (!checkApiIntialized(callback)) return; 33654 33655 if (callback == undefined && jQuery.isFunction(otherNotificationType)) { 33656 callback = otherNotificationType; 33657 otherNotificationType = null; 33658 } 33659 33660 var query = null;
33661 if (otherNotificationType != null && otherNotificationType != "") { 33662 query = "otherNotificationType=" + escape(otherNotificationType); 33663 } 33664 33665 var url = _buildAPIUrl("UpdateRecordTypeAlert", [recordTypeID, recordState, moderatorID], query); 33666 33667 jQuery.getJSON(url, callback); 33668 } 33669 33670 API.DeleteRecordTypeAlert = function (recordTypeID, recordState, moderatorID, otherNotificationType, callback) { 33671 /// <summary> 33672 /// Deletes a RecordTypeAlert. 33673 /// </summary> 33674 /// <param name="recordTypeID"></param> 33675 /// <param name="recordState"></param> 33676 /// <param name="moderatorID"></param> 33677 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33678 33679 if (!checkApiIntialized(callback)) return; 33680 33681 if (callback == undefined && jQuery.isFunction(otherNotificationType)) { 33682 callback = otherNotificationType; 33683 otherNotificationType = null; 33684 } 33685 33686 var query = null; 33687 if (otherNotificationType != null && otherNotificationType != "") { 33688 query = "otherNotificationType=" + escape(otherNotificationType); 33689 } 33690 33691 var url = _buildAPIUrl("DeleteRecordTypeAlert", [recordTypeID, recordState, moderatorID], query); 33692 33693 jQuery.getJSON(url, callback); 33694 } 33695 33696 API.GetRecordTypeAlerts = function (recordTypeID, callback) { 33697 /// <summary> 33698 /// Gets the RecordTypeAlerts from a specific recordTypeID 33699 /// </summary> 33700 /// <param name="recordTypeID"></param> 33701 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33702 33703 if (!checkApiIntialized(callback)) return; 33704 33705 var url = _buildAPIUrl("GetRecordTypeAlerts", [recordTypeID]); 33706 33707 jQuery.getJSON(url, callback); 33708 } 33709 33710 33711 API.ClearCache = function (cacheKey, callback) { 33712 /// <summary> 33713 /// Clears the cache for a given cache key that was previously passed into the SearchRecords call in the SearchArg parameter. 33714 /// </summary> 33715 /// <param name="cacheKey">A cache key that was previously passed into the SearchRecords call in the SearchArg parameter.</param> 33716 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33717 33718 if (!checkApiIntialized(callback)) return; 33719 33720 var url = _buildAPIUrl("ClearCache", [cacheKey]); 33721 33722 jQuery.getJSON(url, callback); 33723 } 33724 33725 33726 API.SaveRecord = function (record, callback, cacheKey) { 33727 /// <summary> 33728 /// Saves a record. 33729 /// </summary> 33730 /// <param name="record">The record to save.</param> 33731 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33732 /// <param name="cacheKey">Optional - the cacheKey to clear the cache for. Use this in conjunction with the same cacheKey on calls to SearchRecords to control the cache.</param> 33733 33734 if (!checkApiIntialized(callback)) return; 33735 33736 if (record == null) callback(API.ResponseType.Error, "The record object cannot be null."); 33737 if (record.RecordTypeName == undefined || record.RecordTypeName == null || record.RecordTypeName == "") { 33738 callback({ 33739 ResponseType: API.ResponseType.Error, 33740 Message: "The RecordTypeName property cannot be null." 33741 }); 33742 return; 33743 } 33744 33745 33746 //get the record type 33747 API.GetRecordTypeByName(record.RecordTypeName, function (response) { 33748 33749 if (response.ResponseType == API.ResponseType.Error) { 33750 callback(response); 33751 return; 33752 } else { 33753 33754 //check the record type 33755 var recordType = response.ResponseData; 33756 if (recordType == undefined || recordType == null) { 33757 callback({ 33758 ResponseType: API.ResponseType.Error, 33759 Message: "The Record Type " + record.RecordTypeName + " could not be found." 33760 }); 33761 return; 33762 } 33763 33764 33765 //validate the field types... 33766 var lstFieldErrors = []; 33767 for (var i = 0; i < recordType.FieldTypes.length; i++) { 33768 var fieldType = recordType.FieldTypes[i];
33769 var fieldValue = record[fieldType.Name]; 33770 33771 if (fieldValue != undefined && fieldValue != null) { 33772 //check for a file value.. 33773 if (fieldValue.OriginalFilePath != undefined) fieldValue = fieldValue.OriginalFilePath; 33774 } 33775 33776 33777 var fieldLabel = recordType.FieldTypes[i].Label; 33778 33779 33780 33781 if (fieldType.AllowNull == false) { 33782 //req field 33783 if (fieldValue == undefined || fieldValue == null || new String(fieldValue).length == 0) { 33784 33785 lstFieldErrors[lstFieldErrors.length] = { 33786 FieldType: fieldType, 33787 Message: "The " + fieldType.Label + " field is required." 33788 }; 33789 } 33790 } 33791 33792 if (fieldValue == undefined || fieldValue == null || fieldValue == "") { 33793 //skip null vals if they are allowed... 33794 continue; 33795 } 33796 33797 33798 switch (fieldType.DataType) { 33799 33800 case API.DataType.Boolean: 33801 if (new String(fieldValue).toLowerCase() != "true" 33802 && new String(fieldValue).toLowerCase() != "false") { 33803 lstFieldErrors[lstFieldErrors.length] = { 33804 FieldType: fieldType, 33805 Message: "Could not convert value " + fieldValue + " from field " + fieldType.Label + " to a boolean." 33806 }; 33807 } 33808 break; 33809 case API.DataType.DateTime: 33810 33811 var dt = new Date(fieldValue); 33812 if (dt == null) { 33813 lstFieldErrors[lstFieldErrors.length] = { 33814 FieldType: fieldType, 33815 Message: "Could not convert value " + fieldValue + " from field " + fieldType.Label + " to a date/time." 33816 }; 33817 } 33818 break; 33819 case API.DataType.Double: 33820 33821 if (isNaN(parseFloat(fieldValue))) { 33822 lstFieldErrors[lstFieldErrors.length] = { 33823 FieldType: fieldType, 33824 Message: "Could not convert value " + fieldValue + " from field " + fieldType.Label + " to a number." 33825 }; 33826 } 33827 break; 33828 case API.DataType.Int: 33829 if (isNaN(parseInt(fieldValue))) { 33830 lstFieldErrors[lstFieldErrors.length] = { 33831 FieldType: fieldType, 33832 Message: "Could not convert value " + fieldValue + " from field " + fieldType.Label + " to a number." 33833 }; 33834 } 33835 break; 33836 case API.DataType.String: 33837 //enforce max length... 33838 if (fieldType.MaxLength == 0 && fieldValue.Length > 400) { 33839 lstFieldErrors[lstFieldErrors.length] = { 33840 FieldType: fieldType, 33841 Message: "The value from field " + fieldType.Label + " must be 400 characters or less." 33842 }; 33843 33844 } 33845 else if (fieldType.MaxLength > 0 && fieldValue.Length > fieldType.MaxLength) { 33846 lstFieldErrors[lstFieldErrors.length] = { 33847 FieldType: fieldType, 33848 Message: "The value from field " + fieldType.Label + " must be " + fieldType.MaxLength + " characters or less." 33849 }; 33850 } 33851 33852 var o1 = _enforceRegex(fieldType, fieldValue, fieldLabel); 33853 if (o1 != null) { 33854 lstFieldErrors[lstFieldErrors.length] = o1; 33855 } 33856 33857 break; 33858 33859 default: 33860 //textblob - enforce max length 33861 33862 if (fieldType.MaxLength > 0 && fieldValue.Length > fieldType.MaxLength) { 33863 lstFieldErrors[lstFieldErrors.length] = { 33864 FieldType: fieldType, 33865 Message: "The value from field " + fieldType.Label + " must be " + fieldType.MaxLength + " characters or less." 33866 }; 33867 } 33868 33869 var o2 = _enforceRegex(fieldType, fieldValue, fieldLabel); 33870 if (o2 != null) { 33871 lstFieldErrors[lstFieldErrors.length] = o2; 33872 } 33873 break; 33874 } 33875 33876 } 33877 33878 //check for validation errors 33879 if (lstFieldErrors.length > 0) { 33880 var msg = ""; 33881 for (var x = 0; x < lstFieldErrors.length; x++) { 33882 msg += " - " + lstFieldErrors[x].Message + "\n"; 33883 } 33884 33885 callback({ 33886 ResponseType: API.ResponseType.Error, 33887 Message: msg, 33888 ValidationErrors: lstFieldErrors 33889 33890 }); 33891 return; 33892 } 33893 33894 33895 33896 //do the deed 33897 var postData = Agility.JSON.encode(record); 33898 if (cacheKey == undefined || cacheKey == null) cacheKey = ""; 33899 33900 var url = _buildAPIUrl("SaveRecord", [], "cacheKey=" + escape(cacheKey)); 33901 33902 _submitPostData(url, postData, callback); 33903 } 33904 }); 33905 33906 } 33907 33908 33909 function _enforceRegex(fieldType, fieldValue, fieldLabel) { 33910 if (fieldValue == undefined || fieldValue == null || fieldValue == "" || typeof fieldValue != "string") return null; 33911 33912 //enfore regex 33913 if (fieldType.ValidationRegEx != null && fieldType.ValidationRegEx != "" && fieldType.ValidationRegEx != "Add comma separated file extensions. Eg: .pdf, .gif") { 33914 try { 33915 var rEx = new RegExp(fieldType.ValidationRegEx); 33916 rEx.ignoreCase = true; 33917 33918 if (fieldValue.search(rEx) == -1) { 33919 33920 33921 if (fieldType.ValidationMessage != null && fieldType.ValidationMessage != "" && fieldType.ValidationMessage != "Add the file type validation message.") { 33922 return { 33923 FieldType: fieldType, 33924 Message: fieldType.ValidationMessage 33925 }; 33926 } 33927 else { 33928 return { 33929 FieldType: fieldType, 33930 Message: "The value from field " + fieldType.Label + " did not match the validation expression requirements." 33931 }; 33932 } 33933 } 33934 } catch (Error) { 33935 //ignore regex errors... 33936 } 33937 } 33938 } 33939 33940 API.SearchRecords = function (searchArg, callback) { 33941 /// <summary> 33942 /// Searches for records based on a SearchArg object. 33943 /// </summary> 33944 /// <param name="searchArg" type="Agility.UGC.API.SearchArg">The search arg object.</param> 33945 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33946 33947 if (!checkApiIntialized(callback)) return; 33948 33949 var argStr = Agility.JSON.encode(searchArg); 33950 var url = _buildAPIUrl("SearchRecords"); 33951 url += "&s=" + escape(argStr); 33952 33953 jQuery.getJSON(url, callback); 33954 33955 } 33956 33957 API.SearchComments = function (commentSearchArg, callback) { 33958 /// <summary> 33959 /// Searches for records based on a SearchArg object. 33960 /// </summary> 33961 /// <param name="commentSearchArg" type="Agility.UGC.API.CommentSearchArg">The search arg object.</param> 33962 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33963 33964 if (!checkApiIntialized(callback)) return; 33965 33966 var argStr = Agility.JSON.encode(commentSearchArg); 33967 var url = _buildAPIUrl("SearchComments"); 33968 url += "&s=" + escape(argStr); 33969 33970 jQuery.getJSON(url, callback); 33971 33972 } 33973 33974 API.SearchCommentParentIDs = function (commentSearchArg, callback) { 33975 /// <summary>
33976 /// Searches for parent record ids for comments based on a SearchArg object. 33977 /// </summary> 33978 /// <param name="commentSearchArg" type="Agility.UGC.API.CommentSearchArg">The search arg object.</param> 33979 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33980 33981 if (!checkApiIntialized(callback)) return; 33982 33983 var argStr = Agility.JSON.encode(commentSearchArg); 33984 var url = _buildAPIUrl("SearchCommentParentIDs"); 33985 url += "&s=" + escape(argStr); 33986 33987 jQuery.getJSON(url, callback); 33988 33989 } 33990 33991 API.GetFeedbackAggregate = function (searchArg, callback) { 33992 /// <summary> 33993 /// Searches for records based on a SearchArg object. 33994 /// </summary> 33995 /// <param name="searchArg" type="Agility.UGC.API.SearchArg">The search arg object.</param> 33996 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 33997 33998 if (!checkApiIntialized(callback)) return; 33999 34000 var argStr = Agility.JSON.encode(searchArg); 34001 var url = _buildAPIUrl("GetFeedbackAggregate"); 34002 url += "&s=" + escape(argStr); 34003 34004 jQuery.getJSON(url, callback); 34005 34006 } 34007 34008 API.SaveRating = function (ratingFeedback, callback) { 34009 var rating = ratingFeedback; 34010 rating.SubmissionType = API.FeedbackSubmissionType.Rating; 34011 API.SaveRatingFeedback(rating, callback); 34012 } 34013 34014 API.SaveLike = function (booleanFeedback, callback) { 34015 var like = booleanFeedback; 34016 like.SubmissionType = API.FeedbackSubmissionType.Like; 34017 like.IsPositive = true; 34018 34019 API.SaveBooleanFeedback(like, callback); 34020 } 34021 34022 API.SaveVote = function (booleanFeedback, callback) { 34023 var vote = booleanFeedback; 34024 vote.IsPositive = true; 34025 vote.SubmissionType = API.FeedbackSubmissionType.Vote; 34026 34027 API.SaveBooleanFeedback(vote, callback); 34028 } 34029 34030 API.SaveApproveDisapprove = function (booleanFeedback, IsApproved, callback) { 34031 var ap = booleanFeedback; 34032 ap.IsPositive = IsApproved; 34033 ap.SubmissionType = API.FeedbackSubmissionType.ApproveDisapprove; 34034 34035 API.SaveBooleanFeedback(ap, callback); 34036 } 34037 34038 34039 API.SaveRatingFeedback = function (ratingFeedback, callback) { 34040 /// <summary> 34041 /// Saves a Rating Feedback Object 34042 /// </summary> 34043 /// <param name="ratingFeedback">The rating feedback to save.</param> 34044 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34045 34046 if (!checkApiIntialized(callback)) return; 34047 34048 if (API.APIProfileRecordID > 0) { 34049 ratingFeedback.ProfileRecordID = API.APIProfileRecordID; 34050 } 34051 34052 var postData = Agility.JSON.encode(ratingFeedback); 34053 34054 var url = _buildAPIUrl("SaveRatingFeedback", null); 34055 34056 _submitPostData(url, postData, callback); 34057 34058 } 34059 34060 API.SaveBooleanFeedback = function (booleanFeedback, callback) { 34061 /// <summary> 34062 /// Saves a boolean feedback object 34063 /// </summary> 34064 /// <param name="booleanFeedback">The boolean feedback to save.</param> 34065 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34066 34067 if (!checkApiIntialized(callback)) return; 34068 34069 if (API.APIProfileRecordID > 0) { 34070 booleanFeedback.ProfileRecordID = API.APIProfileRecordID; 34071 } 34072 34073 34074 34075 var postData = Agility.JSON.encode(booleanFeedback); 34076 34077 var url = _buildAPIUrl("SaveBooleanFeedback", null); 34078 34079 _submitPostData(url, postData, callback); 34080 34081 } 34082 34083 var _settingsCache = null; 34084 34085 API.GetSettings = function (callback, ignoreCache) { 34086 /// <summary> 34087 /// Get the Settings. 34088 /// </summary> 34089 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34090 /// <param name="ignoreCache" type="Boolean">Whether to ignore the cached value and get the settings from the server every time.<param> 34091 34092 if (!checkApiIntialized(callback)) return; 34093 34094 if (_settingsCache == null || ignoreCache == false) { 34095 34096 var url = _buildAPIUrl("GetSettings", null); 34097 34098 jQuery.getJSON(url, function (data) { 34099 if (data.ResponseType != API.ResponseType.OK) { 34100 callback(data); 34101 } else { 34102 _settingsCache = data.ResponseData; 34103 callback(data); 34104 } 34105 }); 34106 } else { 34107 34108 //use the cached value... 34109 callback({ 34110 ResponseType: API.ResponseType.OK, 34111 ResponseData: _settingsCache 34112 }); 34113 } 34114 34115 } 34116
34117 API.SaveSettings = function (settings, callback) { 34118 /// <summary> 34119 /// Saves the Settings 34120 /// </summary> 34121 /// <param name="settings">The settings to save.</param> 34122 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34123 34124 if (!checkApiIntialized(callback)) return; 34125 34126 _settingsCache = null; 34127 34128 var postData = Agility.JSON.encode(settings); 34129 34130 var url = _buildAPIUrl("SaveSettings", null); 34131 34132 _submitPostData(url, postData, callback); 34133 34134 } 34135 34136 API.GetAllSyndicationServices = function (callback) { 34137 /// <summary> 34138 /// Gets all of the syndication services that have been configured. 34139 /// </summary> 34140 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34141 34142 if (!checkApiIntialized(callback)) return; 34143 34144 var url = _buildAPIUrl("GetAllSyndicationServices", null); 34145 34146 jQuery.getJSON(url, callback); 34147 34148 } 34149 34150 API.DeleteSyndicationService = function (syndicationServiceID, callback) { 34151 /// <summary> 34152 /// Deletes a syndication service. 34153 /// </summary> 34154 /// <param name="syndicationServiceID" type="Number">The ID of the syndication service</param> 34155 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34156 34157 if (!checkApiIntialized(callback)) return; 34158 34159 var url = _buildAPIUrl("DeleteSyndicationService", [syndicationServiceID]); 34160 34161 jQuery.getJSON(url, callback); 34162 34163 } 34164 34165 34166 API.SaveSyndicationService = function (syndicationService, callback) { 34167 /// <summary> 34168 /// Saves the Settings 34169 /// </summary> 34170 /// <param name="syndicationService">The settings to save.</param> 34171 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34172 34173 if (!checkApiIntialized(callback)) return; 34174 34175 var postData = Agility.JSON.encode(syndicationService); 34176 34177 var url = _buildAPIUrl("SaveSyndicationService", null); 34178 34179 _submitPostData(url, postData, callback); 34180 34181 } 34182 34183 34184 API.GetAllSystemAccess = function (callback) { 34185 /// <summary> 34186 /// Gets all of the System Access names in the system/ 34187 /// </summary> 34188 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34189 34190 if (!checkApiIntialized(callback)) return; 34191 34192 var url = _buildAPIUrl("GetAllSystemAccess", null); 34193 34194 jQuery.getJSON(url, callback); 34195 34196 } 34197 34198 API.GetGUID = function (callback) { 34199 /// <summary> 34200 /// Get a GUID. 34201 /// </summary> 34202 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34203 34204 if (!checkApiIntialized(callback)) return; 34205 34206 var url = _buildAPIUrl("GetGUID", null); 34207 34208 jQuery.getJSON(url, callback); 34209 } 34210 34211 34212 34213 API.GetAmazonS3Signature = function (policy, callback) { 34214 /// <summary> 34215 /// Gets a signature for an Amazon S3 call. 34216 /// </summary> 34217 /// <param name="policy" type="String"></param> 34218 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34219 34220 if (!checkApiIntialized(callback)) return; 34221 34222 var url = _buildAPIUrl("GetAmazonS3Signature", null, "policy=" + escape(policy)); 34223 34224 jQuery.getJSON(url, callback); 34225 34226 } 34227 34228 API.GetOoyalaSignature = function (queryString, callback) { 34229 /// <summary> 34230 /// Gets a signature for an Ooyala upload. 34231 /// </summary> 34232 /// <param name="queryString" type="String"></param> 34233 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34234 34235 if (!checkApiIntialized(callback)) return; 34236 34237 var url = _buildAPIUrl("GetOoyalaSignature", null, "p=" + escape(queryString)); 34238 34239 jQuery.getJSON(url, callback); 34240 34241 } 34242 34243 API.DeleteFile = function (key, callback) { 34244 /// <summary> 34245 /// Deletes a file from the Amazon S3 bucket 34246 /// </summary> 34247 /// <param name="key" type="String">The full key that points to the file in S3.</param> 34248 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34249 34250 if (!checkApiIntialized(callback)) return; 34251 34252 var url = _buildAPIUrl("DeleteFile", null, "key=" + escape(key)); 34253 34254 jQuery.getJSON(url, callback); 34255 34256 } 34257 34258 var _fileSizeCache = {}; 34259 34260 API.GetFileSize = function (key, callback) { 34261 /// <summary> 34262 /// Get the file size from a file in the Amazon S3 bucket. 34263 /// </summary> 34264 /// <param name="key" type="String">The full key that points to the file in S3.</param> 34265 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 34266 34267 if (!checkApiIntialized(callback)) return; 34268 34269 var url = _buildAPIUrl("GetFileSize", null, "key=" + escape(key)); 34270 34271 if (_fileSizeCache[key] == undefined) { 34272 jQuery.getJSON(url, function (data) { 34273 if (data.ResponseType == API.ResponseType.OK) { 34274 _fileSizeCache[key] = new Number(data.ResponseData); 34275 } 34276 callback(data); 34277 }); 34278 } else { 34279 callback({ 34280 ResponseType: API.ResponseType.OK, 34281 ResponseData: new Number(_fileSizeCache[key]) 34282 }); 34283 } 34284 34285 } 34286 34287 34288 34289 API.TestBrightcoveAuthenticationSettings = function (readToken, writeToken, callback) { 34290 34291 var url = API.APIUrl.toLowerCase().replace("agility-ugc-api-jsonp.svc", "TestBrightcoveAuth.ashx"); 34292 34293 if ($.isFunction(writeToken)) { 34294 34295 var videoID = readToken; 34296 callback = writeToken; 34297 34298 url += "?accessKey=" + escape(API.APIAccessKey); 34299 url += "&seconds=" + escape(API.APISeconds); 34300 url += "&randomNumber=" + escape(API.APIRandomNumber); 34301 url += "&hash=" + escape(API.APIHash); 34302 url += "&profileRecordID=" + escape(API.APIProfileRecordID); 34303 url += "&videoID=" + videoID; 34304 url += "&method=?"; 34305 34306 } else { 34307 34308 url = API.APIUrl.toLowerCase().replace("agility-ugc-api-jsonp.svc", "TestBrightcoveAuth.ashx"); 34309 url += "?readToken=" + escape(readToken); 34310 url += "&writeToken=" + escape(writeToken); 34311 url += "&method=?"; 34312 } 34313 jQuery.getJSON(url, function (retObj) { 34314 var isDisabled = false; 34315 if (retObj.videoIsDisabled != undefined && retObj.videoIsDisabled == true) isDisabled = true; 34316 callback(retObj.valid, retObj.videoExists, isDisabled); 34317 }); 34318 }; 34319 34320 API.TestYouTubeAuthenticationSettings = function (applicationName, apiKey, username, password, callback) { 34321 34322 var url = API.APIUrl.toLowerCase().replace("agility-ugc-api-jsonp.svc", "TestYouTubeAuth.ashx"); 34323 url += "?applicationName=" + escape(applicationName); 34324 url += "&apiKey=" + escape(apiKey); 34325 url += "&username=" + escape(username); 34326 url += "&password=" + escape(password); 34327 url += "&method=?"; 34328 34329 jQuery.getJSON(url, callback); 34330 }; 34331 34332 API.TestAmazonS3AuthenticationSettings = function (bucket, apiKey, secretKey, callback) { 34333 var url = API.APIUrl.toLowerCase().replace("agility-ugc-api-jsonp.svc", "TestAmazonAuth.ashx"); 34334 url += "?apiKey=" + escape(apiKey); 34335 url += "&bucket=" + escape(bucket); 34336 url += "&secretKey=" + escape(secretKey); 34337 url += "&method=?"; 34338 34339 jQuery.getJSON(url, callback); 34340 34341 } 34342 34343 API.GenerateTwitterOauthRequestToken = function (key, secret, callback) { 34344 34345 var url = API.APIUrl.toLowerCase().replace("agility-ugc-api-jsonp.svc", "GenerateTwitterOauthRequestToken.ashx"); 34346 url += "?accessKey=" + escape(API.APIAccessKey); 34347 url += "&seconds=" + escape(API.APISeconds); 34348 url += "&randomNumber=" + escape(API.APIRandomNumber); 34349 url += "&hash=" + escape(API.APIHash); 34350 url += "&profileRecordID=" + escape(API.APIProfileRecordID); 34351 url += "&appkey=" + escape(key); 34352 url += "&appsecret=" + escape(secret); 34353 url += "&method=?"; 34354 34355 34356 jQuery.getJSON(url, callback); 34357 34358 } 34359 34360 API.GetAmazonS3Form = function (options) { 34361 34362 /// <summary> 34363 /// Builds the SWF form uploader that will upload data to Amazon S3. The HTML will be appended to the jQuery element that is passed into the options argument (options.fieldPanel) 34364 /// </summary> 34365 /// <param name="options">The options for this input. Has the following properties: fieldName, inputID, fieldType fieldPanel, swfUploadUrl, beforeUpload, uploadComplete, uploadError, uploadProgress, uploadButtonImageUrl, uploadButtonImageHeight, uploadButtonImageWidth, </param> 34366 34367 if (options == undefined || options == null || typeof (options) == "string") { 34368 throw new Error("The Amazon S3 form parameters have not been set correctly."); 34369 } 34370 34371 var returnUrl = location.href; 34372 var inputID = options.inputID; 34373 var fieldPanel = options.fieldPanel; 34374 var fieldName = options.fieldName; 34375 34376 var fieldType = null; 34377 34378 34379 if (options.fieldType != undefined) fieldType = options.fieldType; 34380 34381 //get the settings... 34382 API.GetSettings(function (data) { 34383 34384 var html = null; 34385 34386 if (data.ResponseType != API.ResponseType.OK) {
34387 html = jQuery("<span>There was an error building the " + options.fieldName + " input: " + data.Message + "</span>"); 34388 html.appendTo(fieldPanel); 34389 return; 34390 } else { 34391 34392 var settings = data.ResponseData; 34393 34394 //if Amazon S3 is NOT enabled, just upload to UGC 34395 if (settings.AmazonS3Bucket == null || settings.AmazonS3Bucket == "") { 34396 API.GetUGCUploadForm(options); 34397 return; 34398 } 34399 34400 //get a new GUID 34401 API.GetGUID(function (dataGUID) { 34402 34403 if (dataGUID.ResponseType != API.ResponseType.OK) { 34404 html = jQuery("<span>There was an error building the " + options.fieldName + " input: " + dataGUID.Message + "</span>"); 34405 html.appendTo(fieldPanel); 34406 return; 34407 } else { 34408 34409 var GUID = dataGUID.ResponseData; 34410 34411 //get the current filename stored in the field 34412 var currentFileKey = $("#" + inputID).val(); 34413 34414 //build the unique ids 34415 var uniqueID = Agility.UniqueID("post_AmazonFileForm"); 34416 var uniqueFormID = uniqueID + "_form"; 34417 var uniqueFileUploadID = uniqueID + "_fileupload"; 34418 34419 var uniqueSwfUploadID = uniqueID + "_swfupload"; 34420 if (options.button_placeholder_id != undefined) { 34421 uniqueSwfUploadID = options.button_placeholder_id; 34422 } 34423 var uniqueIFrameID = uniqueID + "_iframe"; 34424 var uniqueUploadProgressID = uniqueID + "_progress"; 34425 34426 //check for flash version... 34427 var flashVersion = Agility.GetFlashVersion(); 34428 34429 //build the return url to come back to the blank.htm page 34430 34431 returnUrl = returnUrl.substring(0, returnUrl.indexOf("/", returnUrl.indexOf("//") + 2)); 34432 returnUrl += Agility.ResolveUrl("~/AgilityRedirector.htm"); 34433 34434 var blankUrl = Agility.ResolveUrl("~/AgilityRedirector.htm"); 34435 34436 34437 var amazonS3Url = settings.AmazonS3BaseUrl; 34438 if (amazonS3Url == undefined || amazonS3Url == null || amazonS3Url == "") { 34439 html = jQuery("The Amazon S3 Base Url settings value has not be provided."); 34440 html.appendTo(fieldPanel); 34441 return; 34442 } 34443 34444 if (amazonS3Url.lastIndexOf("/") != amazonS3Url.length - 1) amazonS3Url += "/"; 34445 34446 //yyyy-MM-dd\\THH:mm:ss.fff\\Z 34447 var exDate = new Date(); 34448 exDate.setDate(exDate.getDate() + 1); 34449 var expiration = exDate.getFullYear() + "-" + (exDate.getMonth() + 1) + "-" + exDate.getDate() + "T" + exDate.getHours() + ":" + exDate.getMinutes() + ":" + exDate.getSeconds() + "." + exDate.getTimezoneOffset() + "Z"; 34450 34451 var baseDirectory = "AgilityUGC/" + GUID; 34452 34453 var contentLengthRangeMin = 0; 34454 var contentLengthRangeMax = 0; 34455 if (fieldType != null && fieldType.MaxLength > 0) { 34456 //convert from kb to bytes... 34457 contentLengthRangeMax = fieldType.MaxLength * 1024; 34458 } 34459 34460 var policy = '{ "expiration": "' + expiration + '", '; 34461 policy += '"conditions": [ '; 34462 policy += ' {"bucket": "' + settings.AmazonS3Bucket + '"}, '; 34463 policy += ' ["starts-with", "$key", "' + baseDirectory + '"], '; 34464 policy += ' {"acl": "public-read"}, '; 34465 if (flashVersion <= 8) { 34466 policy += ' {"success_action_redirect": "' + returnUrl + '"}, '; 34467 } else { 34468 policy += ' {"success_action_status": "201"}, '; 34469 34470 } 34471 policy += ' ["starts-with", "$Content-Type", ""], [ "starts-with", "$filename", "" ], '; 34472 if (contentLengthRangeMax > 0) { 34473 policy += ' ["content-length-range", ' + contentLengthRangeMin + ', ' + contentLengthRangeMax + '], '; 34474 } 34475 34476 policy += '] }'; 34477 34478 34479 34480 //build the key 34481 var awsSecretKey = settings.AmazonS3SecretKey; 34482 var awskey = settings.AmazonS3AccessKey; 34483 34484 //get the signature from the UGC Server 34485 API.GetAmazonS3Signature(policy, function (data) { 34486 var policySig = data.ResponseData; 34487 34488 34489 var fileTypes = null; 34490 //assume that the file extensions are the validation.... eg: .*([\.jpg]|[\.gif]|[\.jpeg]|[\.png]) 34491 if (fieldType != null && fieldType.ValidationRegEx != undefined && fieldType.ValidationRegEx != "") { 34492
34493 var validExp = fieldType.ValidationRegEx; 34494 validExp = validExp.replace(".*([\\", ""); 34495 validExp = validExp.replace("])", ""); 34496 34497 while (validExp.indexOf("]|[\\") != -1) { 34498 validExp = validExp.replace("]|[\\", ";"); 34499 } 34500 fileTypes = validExp.replace(/\./g, "*."); 34501 34502 } 34503 34504 //IF FLASH IS ENABLED AND swfUpload is defined... 34505 if (Agility.GetFlashVersion() > 8 34506 && options.swfUploadUrl != undefined 34507 && options.swfUploadUrl != null) { 34508 html = jQuery("<span id='" + uniqueSwfUploadID + "'></span>"); 34509 34510 html.appendTo(fieldPanel); 34511 34512 var postParams = { 34513 "AWSAccessKeyId": awskey, 34514 "policy": policySig.PolicyBase64, 34515 "acl": "public-read", 34516 "Signature": policySig.Signature, 34517 "success_action_status": "201" 34518 }; 34519 34520 34521 //build the upload swf 34522 var swfu = new SWFUpload({ 34523 // Backend Settings 34524 upload_url: amazonS3Url, 34525 file_post_name: "file", 34526 post_params: postParams, 34527 34528 // File Upload Settings 34529 file_size_limit: contentLengthRangeMax / 1024, 34530 file_types: fileTypes, 34531 file_types_description: "Valid File Types", 34532 file_upload_limit: "0", // Zero means unlimited 34533 34534 34535 // Event Handler Settings - these functions as defined in Handlers.js 34536 // The handlers are not part of SWFUpload but are part of my website and control how 34537 // my website reacts to the SWFUpload events. 34538 file_queue_error_handler: function (file, errorCode, message) { 34539 jQuery("#" + options.inputID).data("uploading", false); 34540 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 34541 options.uploadError(file, errorCode, message); 34542 } 34543 }, 34544 file_dialog_complete_handler: function (numFilesSelected, numFilesQueued) { 34545 if (numFilesQueued > 0) { 34546 var file = this.getFile(); 34547 if (file == null) return; 34548 34549 var filename = file.name; 34550 34551 //get the mimetype 34552 var mimetype = API.GetMIMEtype(filename); 34553 this.addPostParam("Content-Type", API.GetMIMEtype(filename)); 34554 34555 //set the key based on the filename, minus any invalid characters... 34556 var filenameStripped = filename.replace(/[^a-zA-Z0-9-_\.]/g, ""); 34557 if (filenameStripped == "" || filenameStripped.lastIndexOf(".") == 0) { 34558 34559 } 34560 34561 34562 this.addPostParam("key", baseDirectory + "/" + filenameStripped); 34563 34564 if (options.beforeUpload != undefined && jQuery.isFunction(options.beforeUpload)) { 34565 if (options.beforeUpload(filename, mimetype, file.size, this) == false) { 34566 return; 34567 } 34568 } 34569 34570 jQuery("#" + options.inputID).data("uploading", true); 34571 this.startUpload(); 34572 } 34573 34574 }, 34575 upload_start_handler: function (file) { 34576 //check that the file name has SOME valid characters in it... 34577 var filenameStripped = file.name.replace(/[^a-zA-Z0-9-_\.]/g, ""); 34578 if (filenameStripped == "" || filenameStripped.lastIndexOf(".") == 0) { 34579 return false; 34580 } 34581 }, 34582 upload_progress_handler: function (file, bytesLoaded) { 34583 if (options.uploadProgress != undefined && jQuery.isFunction(options.uploadProgress)) { 34584 options.uploadProgress(file, bytesLoaded); 34585 } 34586 }, 34587 upload_success_handler: function (file, serverData) { 34588 34589 if (jQuery.browser.msie) { 34590 var xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); 34591 xmlDoc.loadXML(serverData); 34592 serverData = xmlDoc; 34593 } 34594 34595 //success - set the value of the input and call the event. 34596 var uploadedKey = $(serverData).find("Key").text(); 34597 if (uploadedKey == null || uploadedKey == "") { 34598 var filenameStripped = file.name.replace(/[^a-zA-Z0-9-_\.]/g, ""); 34599 uploadedKey = baseDirectory + "/" + filenameStripped; 34600 } 34601 34602 jQuery("#" + options.inputID).val(uploadedKey); 34603 jQuery("#" + options.inputID).data("uploading", false); 34604 if (options.uploadComplete != undefined && jQuery.isFunction(options.uploadComplete)) { 34605 options.uploadComplete(uploadedKey, file.size); 34606 } 34607 }, 34608 upload_complete_handler: function (file) { 34609 jQuery("#" + options.inputID).data("uploading", false); 34610 }, 34611 34612 upload_error_handler: function uploadError(file, errorCode, message) { 34613 jQuery("#" + options.inputID).data("uploading", false); 34614 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 34615 options.uploadError(file, errorCode, message); 34616 } 34617 }, 34618 swfupload_loaded_handler: function () { 34619 34620 }, 34621 34622 // Button settings 34623 button_image_url: options.uploadButtonImageUrl, 34624 button_placeholder_id: uniqueSwfUploadID, 34625 button_width: options.uploadButtonImageWidth, 34626 button_height: options.uploadButtonImageHeight, 34627 button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT, 34628 button_action: SWFUpload.BUTTON_ACTION.SELECT_FILE, 34629 button_cursor: SWFUpload.CURSOR.HAND, 34630 34631 34632 // Flash Settings 34633 prevent_swf_caching: false, 34634 flash_url: options.swfUploadUrl, // Relative to this file 34635 34636 // Debug Settings 34637 debug: false 34638 });
34639 34640 34641 34642 } else { 34643 34644 //flash not enabled... 34645 34646 //build the html for the form and iframe 34647 var formHtml = "<form enctype=\"multipart/form-data\" id=\"" + uniqueFormID + "\" method=\"post\" action=\"" + amazonS3Url + "\" target=\"" + uniqueIFrameID + "\" style=\"display:inline\">"; 34648 formHtml += "<input type=\"hidden\" name=\"key\" />"; 34649 formHtml += "<input type=\"hidden\" name=\"AWSAccessKeyId\" />"; 34650 formHtml += "<input type=\"hidden\" name=\"Content-Type\" value=\"\">"; 34651 formHtml += "<input type=\"hidden\" name=\"success_action_redirect\" value=\"" + returnUrl + "\" />"; 34652 formHtml += "<input type=\"hidden\" name=\"acl\" value=\"public-read\" />"; 34653 formHtml += "<input type=\"hidden\" name=\"policy\" value=\"\" />"; 34654 formHtml += "<input type=\"hidden\" name=\"filename\" value=\"\" />"; 34655 formHtml += "<input type=\"hidden\" name=\"Signature\" size=\"100\" value=\"\" />"; 34656 formHtml += "<input id='" + uniqueFileUploadID + "' type=\"file\" name=\"file\" />"; 34657 formHtml += "</form>" 34658 formHtml += "<iframe id=\"" + uniqueIFrameID + "\" name=\"" + uniqueIFrameID + "\" src=\"" + blankUrl + "\" style='position:absolute; height:1px; width: 1px; top:-1px; left: -10000px; overflow:hidden'></iframe>"; 34659 34660 //build the jQuery object for the form 34661 html = jQuery(formHtml); 34662 34663 //add the form to the field panel.. 34664 html.appendTo(fieldPanel); 34665 34666 //set the field values... 34667 jQuery("input[name='AWSAccessKeyId']", html).val(awskey); 34668 jQuery("input[name='policy']", html).val(policySig.PolicyBase64); 34669 jQuery("input[name='Signature']", html).val(policySig.Signature); 34670 34671 34672 34673 var uploadedFileName = null; 34674 34675 //listen to frame load events 34676 jQuery("#" + uniqueIFrameID).load(function () { 34677 //load event of the iframe... 34678 34679 jQuery("#" + uniqueFileUploadID).show(); 34680 34681 var loc = null; 34682 try { 34683 loc = $(this.contentDocument.location) 34684 } catch (error) { } 34685 34686 try { 34687 34688 if (loc == undefined || loc == null) { 34689 loc = $(this.contentWindow.location) 34690 } 34691 34692 var href = loc.attr("href"); 34693 34694 var key = Agility.QueryString("key", href); 34695 if (key != null && key != "") { 34696 var url = amazonS3Url + key; 34697 34698 //update the input file... 34699 jQuery("#" + inputID).val(key); 34700 $("#" + inputID).data("uploading", false); 34701 34702 //call the uploadComplete event, pass it the key 34703 if (options.uploadComplete != undefined && jQuery.isFunction(options.uploadComplete)) { 34704 options.uploadComplete(key, -1); 34705 } 34706 } 34707 } catch (Error) { 34708 $("#" + inputID).data("uploading", false); 34709 34710 34711 //call the uploadError event, pass it the Error object 34712 var errorMsg = "An error occurred while uploading." 34713 if (contentLengthRangeMax > 0) { 34714 errorMsg += " Please ensure the file is less than " + (contentLengthRangeMax / 1024) + "kb."; 34715 } 34716 34717 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 34718 options.uploadError("", -1, errorMsg); 34719 throw Error; 34720 } else { 34721 alert(errorMsg); 34722 throw Error; 34723 } 34724 } 34725 });
34726 34727 //listen to file name changed events... 34728 jQuery("input[name='file']", html).change(function () { 34729 uploadedFileName = $(this).val(); 34730 34731 if (uploadedFileName != "") { 34732 34733 //check that filename is of the allowable types... 34734 if (fieldType != null) { 34735 try { 34736 if (!validateFileType(uploadedFileName, fieldType.ValidationRegEx)) { 34737 34738 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 34739 options.uploadError(uploadedFileName, SWFUpload.QUEUE_ERROR.INVALID_FILETYPE, fieldType.ValidationMessage); 34740 } 34741 34742 $(this).val(""); 34743 return; 34744 } 34745 34746 } catch (ex3) { 34747 return; 34748 } 34749 } 34750 34751 //ensure there are some valid characters in there... 34752 var unstrippedName = uploadedFileName; 34753 var uploadedFileName = uploadedFileName.replace(/[^a-zA-Z0-9-_\.]/g, ""); 34754 if (uploadedFileName == "" || uploadedFileName.lastIndexOf(".") == 0) { 34755 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 34756 options.uploadError(unstrippedName, SWFUpload.QUEUE_ERROR.INVALID_FILETYPE, fieldType.ValidationMessage); 34757 } 34758 $(this).val(""); 34759 return; 34760 } 34761 34762 //set the "key" field value based on the stripped file name 34763 jQuery("input[name='key']", html).val(baseDirectory + "/" + uploadedFileName); 34764 34765 //get the mimeType of the file 34766 var mimeType = API.GetMIMEtype(uploadedFileName); 34767 34768 var filesize = -1; 34769 34770 try { 34771 if (this.files && this.files.length > 0) { 34772 filesize = this.files[0].size; 34773 } 34774 } catch (error) { } 34775 34776 //fire the beforeUpload event 34777 if (options.beforeUpload != undefined && jQuery.isFunction(options.beforeUpload)) { 34778 if (options.beforeUpload(uploadedFileName, mimeType, filesize, null) == false) { 34779 try { 34780 $(this).val(""); 34781 } catch (ex2) { } 34782 return; 34783 } 34784 } 34785 34786 34787 //put a marker on the file to show that it has changed... 34788 $("#" + inputID).data("uploading", true); 34789 $("#" + uniqueFormID + " input[name='Content-Type']").val(mimeType); 34790 34791 //submit the form 34792 var f = jQuery("#" + uniqueFormID); 34793 $(this).hide(); 34794 f.submit(); 34795 34796 //clear out the input and hide it 34797 try { 34798 $(this).val(""); 34799 } catch (ex1) { } 34800 34801 } 34802 34803 });
34804 34805 } 34806 34807 }); 34808 34809 } 34810 34811 }); 34812 34813 } 34814 34815 }); 34816 34817 34818 34819 34820 34821 //bind a "live" event to the remove link (this will work for ANY remove link...); 34822 if (API._liveAttachmentRemoveHandlerBound != true) { 34823 34824 API._liveAttachmentRemoveHandlerBound = true; 34825 34826 jQuery("form a.UploadedFileRemove").live("click", function () { 34827 if (confirm("Do you wish to delete this file?\n\nYou will not be able to recover this file, and any links to it will be broken")) { 34828 34829 //get the associated field ID from the <form> tag 34830 var associatedFieldID = jQuery(this).parents("form").data("associatedFieldID"); 34831 34832 var elem = jQuery(this).parent("span.UploadedFileContainer") 34833 elem.html("Deleting file..."); 34834 34835 var key = jQuery("#" + associatedFieldID).val(); 34836 API.DeleteFile(key, function (data) { 34837 if (data.ResponseType != 0) { 34838 elem.html("An error occurred: " + data.Message); 34839 } else { 34840 elem.html(""); 34841 jQuery("#" + associatedFieldID).val(""); 34842 } 34843 }); 34844 } 34845 }); 34846 } 34847 } 34848 34849 function validateFileType(filepath, validExp) { 34850 34851 if (validExp == null || validExp == "") return true; 34852 34853 validExp = validExp.replace(".*([\\", ""); 34854 validExp = validExp.replace("])", ""); 34855 34856 while (validExp.indexOf("]|[\\") != -1) { 34857 validExp = validExp.replace("]|[\\", ";"); 34858 } 34859 fileTypes = validExp.replace(/\./g, "*."); 34860 34861 var ary = fileTypes.split(";"); 34862 34863 var selectedExt = filepath.substring(filepath.lastIndexOf(".")).toLowerCase(); 34864 if (selectedExt.indexOf(".") != -1) { 34865 selectedExt = selectedExt.substring(selectedExt.lastIndexOf(".")).toLowerCase(); 34866 } 34867 34868 for (var i in ary) { 34869 var ext = $.trim(ary[i]); 34870 if (ext == "" || ext.length < 2 || ext.indexOf("*") != 0) continue; 34871 ext = ext.substring(1).toLowerCase(); 34872 if (ext == selectedExt) { 34873 return true; 34874 } 34875 } 34876 34877 return false; 34878 34879 } 34880 34881 API.GetUGCUploadForm = function (options) { 34882 34883 /// <summary> 34884 /// Builds the SWF form uploader that will upload data to UGC. The HTML will be appended to the jQuery element that is passed into the options argument (options.fieldPanel) 34885 /// </summary> 34886 /// <param name="options">The options for this input. Has the following properties: fieldName, inputID, fieldType fieldPanel, swfUploadUrl, beforeUpload, uploadComplete, uploadError, uploadProgress, uploadButtonImageUrl, uploadButtonImageHeight, uploadButtonImageWidth, </param> 34887 34888 if (options == undefined || options == null || typeof (options) == "string") { 34889 throw new Error("The upload form parameters have not been set correctly."); 34890 } 34891 34892 var returnUrl = location.href; 34893 var inputID = options.inputID; 34894 var fieldPanel = options.fieldPanel; 34895 var fieldName = options.fieldName; 34896 34897 var fieldType = null; 34898 34899 34900 if (options.fieldType != undefined) fieldType = options.fieldType; 34901 34902 //get the current filename stored in the field 34903 var currentFileKey = $("#" + inputID).val(); 34904 34905 //build the unique ids 34906 var uniqueID = Agility.UniqueID("post_UGCFileForm"); 34907 var uniqueFormID = uniqueID + "_form"; 34908 var uniqueFileUploadID = uniqueID + "_fileupload"; 34909 34910 34911 var uniqueSwfUploadID = uniqueID + "_swfupload"; 34912 if (options.button_placeholder_id != undefined) { 34913 uniqueSwfUploadID = options.button_placeholder_id; 34914 } 34915 34916 var uniqueIFrameID = uniqueID + "_iframe"; 34917 var uniqueUploadProgressID = uniqueID + "_progress"; 34918 34919 //check for flash version... 34920 var flashVersion = Agility.GetFlashVersion(); 34921 34922 //build the return url to come back to the blank.htm page 34923 34924 returnUrl = returnUrl.substring(0, returnUrl.indexOf("/", returnUrl.indexOf("//") + 2)); 34925 returnUrl += Agility.ResolveUrl("~/AgilityRedirector.htm"); 34926 34927 var blankUrl = Agility.ResolveUrl("~/AgilityRedirector.htm"); 34928 34929 34930 var uploadUrl = API.APIUrl; 34931 uploadUrl = uploadUrl.substring(0, uploadUrl.toLowerCase().lastIndexOf("/")) + "/UploadFile.ashx"; 34932 34933 //yyyy-MM-dd\\THH:mm:ss.fff\\Z 34934 var exDate = new Date(); 34935 exDate.setDate(exDate.getDate() + 1); 34936 var expiration = exDate.getFullYear() + "-" + (exDate.getMonth() + 1) + "-" + exDate.getDate() + "T" + exDate.getHours() + ":" + exDate.getMinutes() + ":" + exDate.getSeconds() + "." + exDate.getTimezoneOffset() + "Z"; 34937 34938 var contentLengthRangeMin = 0; 34939 var contentLengthRangeMax = 0; 34940 if (fieldType != null && fieldType.MaxLength > 0) { 34941 //convert from kb to bytes... 34942 contentLengthRangeMax = fieldType.MaxLength * 1024; 34943 } 34944 34945 var fileTypes = null; 34946 //assume that the file extensions are the validation.... eg: .*([\.jpg]|[\.gif]|[\.jpeg]|[\.png]) 34947 if (fieldType != null && fieldType.ValidationRegEx != undefined && fieldType.ValidationRegEx != "") { 34948
34949 var validExp = fieldType.ValidationRegEx; 34950 validExp = validExp.replace(".*([\\", ""); 34951 validExp = validExp.replace("])", ""); 34952 34953 while (validExp.indexOf("]|[\\") != -1) { 34954 validExp = validExp.replace("]|[\\", ";"); 34955 } 34956 fileTypes = validExp.replace(/\./g, "*."); 34957 34958 } 34959 34960 //IF FLASH IS ENABLED.... 34961 34962 if (Agility.GetFlashVersion() > 8 34963 && options.swfUploadUrl != undefined 34964 && options.swfUploadUrl != null) { 34965 34966 if (options.button_placeholder_id == undefined) { 34967 html = jQuery("<span id='" + uniqueSwfUploadID + "'></span>"); 34968 html.appendTo(fieldPanel); 34969 } 34970 34971 var button_window_mode = SWFUpload.WINDOW_MODE.TRANSPARENT; 34972 if (options.button_window_mode != undefined) button_window_mode = options.button_window_mode; 34973 34974 34975 var postParams = { 34976 "accessKey": API.APIAccessKey, 34977 "seconds": API.APISeconds, 34978 "randomNumber": API.APIRandomNumber, 34979 "hash": API.APIHash, 34980 "profileRecordID": API.APIProfileRecordID 34981 }; 34982 34983 34984 //build the upload swf 34985 var swfu = new SWFUpload({ 34986 // Backend Settings 34987 upload_url: uploadUrl, 34988 file_post_name: "file", 34989 post_params: postParams, 34990 34991 // File Upload Settings 34992 file_size_limit: contentLengthRangeMax / 1024, 34993 file_types: fileTypes, 34994 file_types_description: "Valid File Types", 34995 file_upload_limit: "0", // Zero means unlimited 34996 34997 34998 // Event Handler Settings - these functions as defined in Handlers.js 34999 // The handlers are not part of SWFUpload but are part of my website and control how 35000 // my website reacts to the SWFUpload events. 35001 file_queue_error_handler: function (file, errorCode, message) { 35002 jQuery("#" + options.inputID).data("uploading", false); 35003 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 35004 options.uploadError(file, errorCode, message); 35005 } 35006 }, 35007 file_dialog_complete_handler: function (numFilesSelected, numFilesQueued) { 35008 if (numFilesQueued > 0) { 35009 var file = this.getFile(); 35010 if (file == null) return; 35011 35012 var filename = file.name; 35013 35014 //get the mimetype 35015 var mimetype = API.GetMIMEtype(filename); 35016 this.addPostParam("Content-Type", API.GetMIMEtype(filename)); 35017 35018 //set the key based on the filename, minus any invalid characters... 35019 var filenameStripped = filename.replace(/[^a-zA-Z0-9-_\.]/g, ""); 35020 if (filenameStripped == "" || filenameStripped.lastIndexOf(".") == 0) { 35021 35022 } 35023 35024 35025 if (options.beforeUpload != undefined && jQuery.isFunction(options.beforeUpload)) { 35026 if (options.beforeUpload(filename, mimetype, file.size, this) == false) { 35027 return; 35028 } 35029 } 35030 35031 jQuery("#" + options.inputID).data("uploading", true); 35032 this.startUpload(); 35033 } 35034 35035 }, 35036 upload_start_handler: function (file) { 35037 //check that the file name has SOME valid characters in it... 35038 var filenameStripped = file.name.replace(/[^a-zA-Z0-9-_\.]/g, ""); 35039 if (filenameStripped == "" || filenameStripped.lastIndexOf(".") == 0) { 35040 return false; 35041 } 35042 }, 35043 upload_progress_handler: function (file, bytesLoaded) { 35044 if (options.uploadProgress != undefined && jQuery.isFunction(options.uploadProgress)) { 35045 options.uploadProgress(file, bytesLoaded); 35046 } 35047 }, 35048 upload_success_handler: function (file, serverData) { 35049 jQuery("#" + options.inputID).data("uploading", false); 35050 35051 //try { 35052 var responseObj = Agility.JSON.decode(serverData); 35053 if (responseObj.ResponseType != API.ResponseType.OK) { 35054 //an error occurred... 35055 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 35056 options.uploadError("", -1, responseObj.Message); 35057 } 35058 } else { 35059 //successful upload... 35060 var uploadedFileName = responseObj.ResponseData; 35061 35062 //update the input file... 35063 jQuery("#" + inputID).val(uploadedFileName); 35064 35065 35066 //call the uploadComplete event, pass it the key 35067 if (options.uploadComplete != undefined && jQuery.isFunction(options.uploadComplete)) { 35068 options.uploadComplete(uploadedFileName, -1); 35069 } 35070 } 35071 35072 /* 35073 } catch (error) { 35074 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 35075 options.uploadError(file, 101, "An error occurred interpretting the results from the server."); 35076 } 35077 } 35078 */ 35079 }, 35080 upload_complete_handler: function (file) { 35081 jQuery("#" + options.inputID).data("uploading", false); 35082 }, 35083 35084 upload_error_handler: function uploadError(file, errorCode, message) { 35085 jQuery("#" + options.inputID).data("uploading", false); 35086 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 35087 options.uploadError(file, errorCode, message); 35088 } 35089 }, 35090 swfupload_loaded_handler: function () { 35091 35092 }, 35093 35094 // Button settings 35095 button_image_url: options.uploadButtonImageUrl, 35096 button_placeholder_id: uniqueSwfUploadID, 35097 button_width: options.uploadButtonImageWidth, 35098 button_height: options.uploadButtonImageHeight, 35099 button_window_mode: button_window_mode, 35100 button_action: SWFUpload.BUTTON_ACTION.SELECT_FILE, 35101 button_cursor: SWFUpload.CURSOR.HAND, 35102 35103 35104 // Flash Settings 35105 prevent_swf_caching: false, 35106 flash_url: options.swfUploadUrl, // Relative to this file 35107 35108 // Debug Settings 35109 debug: false 35110 }); 35111 35112 35113 35114 } 35115 else { 35116 35117 //flash not enabled... 35118 35119 //build the html for the form and iframe 35120 var formHtml = "<form enctype=\"multipart/form-data\" id=\"" + uniqueFormID + "\" method=\"post\" action=\"" + uploadUrl + "\" target=\"" + uniqueIFrameID + "\" style=\"display:inline\">"; 35121 35122 formHtml += "<input type=\"hidden\" name=\"accessKey\" />"; 35123 formHtml += "<input type=\"hidden\" name=\"seconds\" />"; 35124 formHtml += "<input type=\"hidden\" name=\"randomNumber\" />"; 35125 formHtml += "<input type=\"hidden\" name=\"hash\" />"; 35126 formHtml += "<input type=\"hidden\" name=\"profileRecordID\" />"; 35127 formHtml += "<input type=\"hidden\" name=\"returnUrl\" />"; 35128 formHtml += "<input id='" + uniqueFileUploadID + "' type=\"file\" name=\"file\" />"; 35129 formHtml += "</form>" 35130 formHtml += "<iframe id=\"" + uniqueIFrameID + "\" name=\"" + uniqueIFrameID + "\" src=\"" + blankUrl + "\" style='position:absolute; height:1px; width: 1px; top:-1px; left: -10000px; overflow:hidden'></iframe>"; 35131 35132 //build the jQuery object for the form 35133 html = jQuery(formHtml); 35134 35135 //add the form to the field panel.. 35136 html.appendTo(fieldPanel); 35137 35138 //set the field values... 35139 jQuery("input[name='accessKey']", html).val(API.APIAccessKey); 35140 jQuery("input[name='seconds']", html).val(API.APISeconds); 35141 jQuery("input[name='randomNumber']", html).val(API.APIRandomNumber); 35142 jQuery("input[name='hash']", html).val(API.APIHash); 35143 jQuery("input[name='profileRecordID']", html).val(API.APIProfileRecordID); 35144 jQuery("input[name='returnUrl']", html).val(returnUrl); 35145 35146 var uploadedFileName = null; 35147 35148 //listen to frame load events 35149 jQuery("#" + uniqueIFrameID).load(function () { 35150 //load event of the iframe... 35151 jQuery("#" + uniqueFileUploadID).show(); 35152 35153 var loc = null; 35154 try { 35155 loc = $(this.contentDocument.location) 35156 } catch (error) { } 35157
35158 try { 35159 35160 if (loc == undefined || loc == null) { 35161 loc = $(this.contentWindow.location) 35162 } 35163 35164 var href = loc.attr("href"); 35165 35166 var responseType = Agility.QueryString("ResponseType", href); 35167 if (responseType == null) return; 35168 35169 if (responseType != API.ResponseType.OK) { 35170 //an error occurred... 35171 var errorMsg = Agility.QueryString("Message", href); 35172 35173 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 35174 options.uploadError("", -1, errorMsg); 35175 } 35176 } else { 35177 //successful upload... 35178 var uploadedFileName = Agility.QueryString("ResponseData", href); 35179 35180 //update the input file... 35181 jQuery("#" + inputID).val(uploadedFileName); 35182 $("#" + inputID).data("uploading", false); 35183 35184 //call the uploadComplete event, pass it the key 35185 if (options.uploadComplete != undefined && jQuery.isFunction(options.uploadComplete)) { 35186 options.uploadComplete(uploadedFileName, -1); 35187 } 35188 } 35189 35190 35191 } catch (Error) { 35192 $("#" + inputID).data("uploading", false); 35193 35194 35195 //call the uploadError event, pass it the Error object 35196 var errorMsg = "An error occurred while uploading." 35197 if (contentLengthRangeMax > 0) { 35198 errorMsg += " Please ensure the file is less than " + (contentLengthRangeMax / 1024) + "kb."; 35199 } 35200 35201 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 35202 options.uploadError("", -1, errorMsg); 35203 throw Error; 35204 } else { 35205 alert(errorMsg); 35206 throw Error; 35207 } 35208 } 35209 }); 35210 35211 //listen to file name changed events... 35212 jQuery("input[name='file']", html).change(function () { 35213 var fileElem = $(this); 35214 var fileDom = this; 35215 uploadedFileName = fileElem.val(); 35216 35217 if (uploadedFileName != "") { 35218 35219 35220 //check that filename is of the allowable types... 35221 if (fieldType != null) { 35222 try { 35223 if (!validateFileType(uploadedFileName, fieldType.ValidationRegEx)) { 35224 35225 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 35226 options.uploadError(uploadedFileName, SWFUpload.QUEUE_ERROR.INVALID_FILETYPE, fieldType.ValidationMessage); 35227 } 35228 35229 fileElem.val(""); 35230 return; 35231 } 35232 35233 } catch (ex3) { 35234 return; 35235 } 35236 } 35237 35238 //ensure there are some valid characters in there... 35239 var unstrippedName = uploadedFileName; 35240 var uploadedFileName = uploadedFileName.replace(/[^a-zA-Z0-9-_\.]/g, ""); 35241 if (uploadedFileName == "" || uploadedFileName.lastIndexOf(".") == 0) { 35242 if (options.uploadError != undefined && jQuery.isFunction(options.uploadError)) { 35243 options.uploadError(unstrippedName, SWFUpload.QUEUE_ERROR.INVALID_FILETYPE, fieldType.ValidationMessage); 35244 } 35245 fileElem.val(""); 35246 return; 35247 } 35248 35249 35250 //get the mimeType of the file 35251 var mimeType = API.GetMIMEtype(uploadedFileName); 35252 35253 var uploaderObj = null; 35254 var filesize = -1; 35255 35256 try { 35257 if (fileDom.files && fileDom.files.length > 0) { 35258 filesize = fileDom.files[0].size; 35259 } 35260 } catch (error) { } 35261 35262 //fire the beforeUpload event 35263 if (options.beforeUpload != undefined && jQuery.isFunction(options.beforeUpload)) { 35264 if (options.beforeUpload(uploadedFileName, mimeType, filesize, uploaderObj) == false) { 35265 try { 35266 fileElem.val(""); 35267 } catch (ex2) { } 35268 return; 35269 } 35270 } 35271 35272 //put a marker on the file to show that it has changed... 35273 $("#" + inputID).data("uploading", true); 35274 $("#" + uniqueFormID + " input[name='Content-Type']").val(mimeType); 35275 35276 //submit the form 35277 var f = jQuery("#" + uniqueFormID); 35278 fileElem.hide(); 35279 f.submit(); 35280 35281 35282 //clear out the input and hide it 35283 try { 35284 fileElem.val(""); 35285 } catch (ex1) { } 35286 35287 } 35288 35289 }); 35290 35291 } 35292 35293 35294 35295 //bind a "live" event to the remove link (this will work for ANY remove link...); 35296 if (API._liveAttachmentRemoveHandlerBound != true) { 35297 35298 API._liveAttachmentRemoveHandlerBound = true; 35299 35300 jQuery("form a.UploadedFileRemove").live("click", function () { 35301 if (confirm("Do you wish to delete this file?\n\nYou will not be able to re
35301cover this file, and any links to it will be broken")) { 35302 35303 //get the associated field ID from the <form> tag 35304 var associatedFieldID = jQuery(this).parents("form").data("associatedFieldID"); 35305 35306 var elem = jQuery(this).parent("span.UploadedFileContainer") 35307 elem.html("Deleting file..."); 35308 35309 var key = jQuery("#" + associatedFieldID).val(); 35310 API.DeleteFile(key, function (data) { 35311 if (data.ResponseType != 0) { 35312 elem.html("An error occurred: " + data.Message); 35313 } else { 35314 elem.html(""); 35315 jQuery("#" + associatedFieldID).val(""); 35316 } 35317 }); 35318 } 35319 }); 35320 } 35321 } 35322 35323 35324 //global variable used to track whether the live attachment remove randler event has been bound 35325 API._liveAttachmentRemoveHandlerBound = false; 35326 35327 35328 35329 function _buildAPIUrl(methodName, args, query) { 35330 var url = API.APIUrl; 35331 if (url == "" || url == null) return null; 35332 //query should be in the form "q1=q1val&s2=s2val 35333 35334 //ensure the url ends with / 35335 if (url.lastIndexOf("/") != url.length - 1) url += "/"; 35336 35337 //create the base url for the call 35338 url += methodName + "/" + API.APIAccessKey + "/" + API.APISeconds + "/" + API.APIRandomNumber + "/" + API.APIHash + "/" + API.APIProfileRecordID; 35339 35340 //add the arguments for call 35341 if (args != undefined && $.isArray(args) && args.length > 0) { 35342 jQuery.each(args, function (index, arg) { 35343 url += "/" + escape(arg); 35344 }); 35345 } 35346 35347 //add the "method" param 35348 url += "?method=?"; 35349 35350 //add the query strings 35351 if (query != undefined && query != "") { 35352 url += "&" + query; 35353 } 35354 35355 return url; 35356 } 35357 35358 35359 35360 function _submitPostData(url, postData, callback) { 35361 35362 //build the unique ids 35363 var uniqueID = Agility.UniqueID("postDataForm"); 35364 35365 var uniqueFormID = uniqueID + "_form"; 35366 var uniqueIFrameID = uniqueID + "_iframe"; 35367 35368 //build the return url to come back to the AgilityRedirector.htm page 35369 var returnUrl = location.href; 35370 returnUrl = returnUrl.substring(0, returnUrl.indexOf("/", returnUrl.indexOf("//") + 2)); 35371 returnUrl += Agility.ResolveUrl("~/AgilityRedirector.htm"); 35372 35373 var blankUrl = Agility.ResolveUrl("~/AgilityRedirector.htm?empty=1"); 35374 35375 //remove the method callback from the url 35376 url = url.replace("?method=?", "?method=post"); 35377 35378 //build the html for the form and iframe 35379 var formHtml = "<div id=\"" + uniqueID + "\" style='display:inline'><form id=\"" + uniqueFormID + "\" method=\"post\" action=\"" + url + "\" target=\"" + uniqueIFrameID + "\">"; 35380 if (typeof postData == "string") { 35381 formHtml += "<input type=\"text\" name=\"postdata\" />"; 35382 } else { 35383 for (prop in postData) { 35384 formHtml += "<input type=\"text\" name=\"" + prop + "\" />"; 35385 } 35386 } 35387 formHtml += "<input type=\"text\" name=\"url\" />"; 35388 formHtml += "</form>" 35389 formHtml += "<iframe id=\"" + uniqueIFrameID + "\" name=\"" + uniqueIFrameID + "\" src=\"" + blankUrl + "\"></iframe>"; 35390 formHtml += "</div>"; 35391 35392 35393 //add the elements to the DOM 35394 var thisBody = jQuery(document.body); 35395 jQuery(thisBody).append(formHtml); 35396 35397 //create the actual DOM elements 35398 var div = jQuery("#" + uniqueID); 35399 var form = jQuery("#" + uniqueFormID); 35400 var iframe = jQuery("#" + uniqueIFrameID); 35401 35402 if (typeof postData == "string") { 35403 $("input[name=postdata]", form).val(postData); 35404 } else { 35405 for (prop in postData) { 35406 $("input[name=" + prop + "]", form).val(postData[prop]); 35407 } 35408 } 35409 35410 35411 $("input[name=url]", form).val(returnUrl); 35412 35413 //capture the load event of the form. 35414 jQuery(iframe).load(function () { 35415 35416 var frm = window.frames[uniqueIFrameID]; 35417 35418 var responseType = responseType = API.ResponseType.Error; 35419 35420 var loc = frm.location; 35421 35422 if (loc != null) { 35423 var href = loc.href; 35424 35425 if (Agility.QueryString("empty", href) == "1") { 35426 //wait until the empty iframe has loaded... 35427 //submit the form 35428 setTimeout(function () { 35429 form.submit(); 35430 }, 0); 35431 return; 35432 35433 } 35434 35435 responseType = parseInt(Agility.QueryString("ResponseType", href)); 35436 if (isNaN(responseType)) responseType = API.ResponseType.Error; 35437 } 35438 35439 35440 var data = { 35441 ResponseType: responseType, 35442 Message: Agility.QueryString("Message", href), 35443 ResponseData: Agility.QueryString("ResponseData", href) 35444 }; 35445 35446 //call the callback 35447 setTimeout(function () { 35448 callback(data); 35449 }, 0); 35450 35451 //remove the elements... 35452 setTimeout(function () { 35453 div.empty(); 35454 }, 0); 35455 35456 }); 35457 35458 35459 } 35460 35461 35462 var _authCookieName = null; 35463 35464 API.GetAuthCookieName = function () { 35465 /// <summary>Gets the name of the cookie that will be used for authentication.</summary> 35466 if (_authCookieName == null) _authCookieName = "UGC_AUTH_" + API.APIAccessKey; 35467 return _authCookieName; 35468 } 35469 35470 API.SetAuthCookieName = function (cookieName) { 35471 /// <summary>Gets the name of the cookie that will be used for authentication.</summary> 35472 return _authCookieName = cookieName; 35473 } 35474 35475 35476 API.Logout = function (websiteUserTypeName) { 35477 /// <summary>Logs a user out of the UGC system and removes their login cookie.</summary> 35478 /// <param name="websiteUserTypeName" type="String">The website user type reference name.</param> 35479 35480 //set the cookie based on the API Access Key 35481 var cookieName = API.GetAuthCookieName(); 35482 if (websiteUserTypeName != null) cookieName += websiteUserTypeName; 35483 var cookieDate = Date.today().addMonths(-1); 35484 var cookieValue = null; 35485 Agility.SetCookie(cookieName, cookieValue, cookieDate, "/", null, true); 35486 35487 } 35488 35489 API.Authenticate = function (websiteUserTypeName, login, password, persist
35489Cookie, loginFieldName, callback) { 35490 /// <summary>Authenticates a user based on their login and password and their website user type reference name. Returns the authentication token on success, empty string on failure. This will also set a cookie that will keep the user logged in for this session, or persist the cookie if desired.</summary> 35491 /// <param name="websiteUserTypeName" type="String">The website user type reference name.</param> 35492 /// <param name="login" type="String">The login, usually a username or email address.</param> 35493 /// <param name="password" type="String">The password.</param> 35494 /// <param name="persistCookie" type="Boolean">(Optional) Whether or not to persist the authentication token in a cookie.</param> 35495 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 35496 35497 if (callback == undefined) { 35498 if (loginFieldName != undefined && $.isFunction(loginFieldName)) { 35499 callback = loginFieldName; 35500 loginFieldName = ""; 35501 } 35502 } 35503 35504 if (callback == undefined) { 35505 if (persistCookie != undefined && $.isFunction(persistCookie)) { 35506 callback = persistCookie; 35507 persistCookie = false; 35508 } 35509 } 35510 35511 if (loginFieldName == undefined) loginFieldName = ""; 35512 35513 if (!checkApiIntialized(callback)) return; 35514 var args = new Array(); 35515 args.push(websiteUserTypeName); 35516 var argStr = Agility.JSON.encode(websiteUserTypeName); 35517 var url = _buildAPIUrl("Authenticate", args); 35518 url += "&l=" + escape(login) + "&p=" + escape(password) + "&fn=" + escape(loginFieldName); 35519 35520 $.getJSON(url, function (data) { 35521 if (_processOdataError(data, callback)) return; 35522 if (data != undefined) { 35523 35524 var token = data.ResponseData; 35525 35526 if (token != undefined && token != null && token != "") { 35527 //set the cookie based on the API Access Key 35528 var cookieName = API.GetAuthCookieName(); 35529 if (websiteUserTypeName != null) cookieName += websiteUserTypeName; 35530 35531 var cookieValue = new String(token); 35532 var cookieDate = null; 35533 if (persistCookie) { 35534 cookieDate = Date.today().addMonths(1); 35535 } 35536 Agility.SetCookie(cookieName, cookieValue, cookieDate, "/", null, false); 35537 } 35538 //return the OK response and the authentication token 35539 callback({ 35540 ResponseType: API.ResponseType.OK, 35541 ResponseData: token, 35542 Message: null 35543 }); 35544 } 35545 }); 35546 35547 } 35548 35549 API.IsAuthenticated = function (websiteUserTypeName, callback) { 35550 /// <summary>Determines if the current user is authenticated and returns the user ID if so. If the profileRecordID returned is less than zero, the user is NOT authenticated.</summary> 35551 /// <param name="websiteUserTypeName" type="String">The website user type reference name to validate the current used based on.</param> 35552 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 35553 35554 //grab the token the from the cookie 35555 var cookieName = API.GetAuthCookieName(); 35556 if (websiteUserTypeName != null) cookieName += websiteUserTypeName; 35557 35558 var token = Agility.GetCookie(cookieName); 35559 35560 35561 if (token == null || token == "") { 35562 callback({ 35563 ResponseType: API.ResponseType.OK, 35564 ResponseData: false, 35565 Message: null 35566 }); 35567 return; 35568 } 35569 35570 if (!checkApiIntialized(callback)) return; 35571 var args = new Array(); 35572 args.push(websiteUserTypeName); 35573 35574 var url = _buildAPIUrl("IsAuthenticated", args); 35575 35576 url += "&s=" + escape(token); 35577 35578 $.getJSON(url, function (data) { 35579 if (data != undefined && data.ResponseData != undefined && data.ResponseData != null) { 35580 35581 35582 var profileRecordID = data.ResponseData.ProfileRecordID; 35583 var seconds = data.ResponseData.Seconds; 35584 var randomNumber = data.ResponseData.RandomNumber; 35585 var hash = data.ResponseData.AccessHash; 35586 var accessKey = data.ResponseData.AccessKey; 35587 35588 //reset the API data for this session 35589 API.APIAccessKey = accessKey; 35590 API.APISeconds = seconds; 35591 API.APIRandomNumber = randomNumber; 35592 API.APIProfileRecordID = profileRecordID; 35593 API.APIHash = hash; 35594 35595 //send results to the user... 35596 callback({ 35597 ResponseType: API.ResponseType.OK, 35598 ResponseData: profileRecordID, 35599 Message: null 35600 }); 35601 } 35602 }); 35603 } 35604 35605 API.ChangePassword = function (currentPassword, newPassword, callback) { 35606 /// <summary>Change the password for the current website user. The ResponseData parameter of the callback will be a true/false if the password change was successful.<summary> 35607 /// <param name="currentPassword" type="String">The user's current password.</param> 35608 /// <param name="newPassword" type="String">The user's new password.</param> 35609 /// <param name="newPassword" type="String">The user's new password.</param> 35610 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 35611 35612 if (API.APIProfileRecordID < 1) { 35613 callback({ 35614 ResponseType: API.ResponseType.Error, 35615 ResponseData: false, 35616 Message: "The user is not currently logged in." 35617 }); 35618 return; 35619 } 35620 35621 35622 35623 if (!checkApiIntialized(callback)) return; 35624 var args = new Array(); 35625
35626 var url = _buildAPIUrl("ChangePassword", args); 35627 url += "&c=" + escape(currentPassword); 35628 url += "&n=" + escape(newPassword); 35629 35630 35631 $.getJSON(url, function (data) { 35632 35633 callback(data); 35634 35635 }); 35636 } 35637 35638 API.RetrievePassword = function (websiteUserTypeName, login, callback) { 35639 /// <summary>Retrieve the password for the profile login name and type. The ResponseData parameter of the callback will be a true/false if the password change was successful.<summary> 35640 /// <param name="websiteUserTypeName" type="String">The website user type reference name.</param> 35641 /// <param name="login" type="String">The user's login (usually username or email address).</param> 35642 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 35643 35644 35645 if (!checkApiIntialized(callback)) return; 35646 var args = new Array(); 35647 args.push(websiteUserTypeName); 35648 35649 var url = _buildAPIUrl("RetrievePassword", args); 35650 url += "&l=" + escape(login); 35651 35652 35653 $.getJSON(url, function (data) { 35654 if (data != undefined && data.ResponseData != undefined && data.ResponseData != null) { 35655 35656 //send results to the user... 35657 callback({ 35658 ResponseType: API.ResponseType.OK, 35659 ResponseData: data.ResponseData, 35660 Message: null 35661 }); 35662 } 35663 }); 35664 } 35665 35666 API.GetODataMetaData = function (callback) { 35667 /// <summary>Gets the OData meta data for this service.</summary> 35668 var url = _getOdataUrl(); 35669 url += "/?$format=json&$callback=?"; 35670 35671 $.getJSON(url, function (data) { 35672 if (data != undefined && data.d != undefined && data.d != null) { 35673 if (_processOdataError(data, callback)) return; 35674 35675 if (data.d != undefined && data.d != null) { 35676 callback({ 35677 ResponseType: API.ResponseType.OK, 35678 Message: null, 35679 ResponseData: data.d 35680 }); 35681 } 35682 } 35683 }); 35684 35685 } 35686 35687 API.GetODataFeed = function (recordTypeName, options, callback) { 35688 35689 var url = _getOdataUrl(); 35690 url += "/" + recordTypeName + "/"; 35691 35692 url += "?$format=json" 35693 35694 if (options != undefined && options != null) { 35695 if (options.filter != undefined && options.filter != null && options.filter != "") { 35696 url += "&$filter=" + escape(options.filter); 35697 } 35698 } 35699 35700 url += "&$callback=?"; 35701 35702 $.getJSON(url, function (data) { 35703 if (_processOdataError(data, callback)) return; 35704 35705 if (data != undefined && data != null) { 35706 if (data.d != undefined && data.d != null && data.d.results != undefined && data.d.results != null) { 35707 callback({ 35708 ResponseType: API.ResponseType.OK, 35709 Message: null, 35710 ResponseData: data.d.results 35711 }); 35712 } 35713 } 35714 }); 35715 35716 } 35717 35718 35719 35720 API.GetODataRecord = function (recordTypeName, recordID, callback) { 35721 var url = _getOdataUrl(); 35722 url += "/" + recordTypeName + "(" + recordID + ")/"; 35723 url += "?$format=json&$callback=?"; 35724 35725 35726 $.getJSON(url, function (data) { 35727 35728 if (_processOdataError(data, callback)) return; 35729 35730 if (data != undefined && data != null) { 35731 if (data.d != undefined && data.d != null) { 35732 callback({ 35733 ResponseType: API.ResponseType.OK, 35734 Message: null, 35735 ResponseData: data.d 35736 }); 35737 } 35738 } 35739 35740 }); 35741 35742 } 35743 35744 35745 API.ExecCustomProcedure = function (proc, paramArgs, callback) { 35746 var url = Agility.UGC.API.APIUrl; 35747 url = url.toLowerCase().replace("agility-ugc-api-jsonp.svc", "ExecCustomProcedure.ashx"); 35748 url += "?proc=" + escape(proc); 35749 35750 if (paramArgs != undefined && paramArgs != null) { 35751 for (var propertyName in paramArgs) { 35752 var val = paramArgs[propertyName]; 35753 if (val == undefined || val == null) continue; 35754 url += "&@" + escape(propertyName) + "=" + escape(paramArgs[propertyName]); 35755 } 35756 } 35757 url += "&method=?"; 35758 url += "&format=json"; 35759 url += "&accessKey=" + escape(API.APIAccessKey); 35760 url += "&seconds=" + escape(API.APISeconds); 35761 url += "&randomNumber=" + escape(API.APIRandomNumber); 35762 url += "&hash=" + escape(API.APIHash); 35763 url += "&profileRecordID=" + escape(API.APIProfileRecordID); 35764 35765 $.getJSON(url, function (data) { 35766 35767 if (data != undefined) { 35768 35769 var obj = { 35770 ResponseType: API.ResponseType.OK, 35771 Message: null 35772 }; 35773 35774 if (data.ResonseData != undefined) { 35775 obj.ResponseData = data.ResonseData; 35776 } else { 35777 obj.ResponseData = data.ResponseData; 35778 } 35779 35780 35781 //send results to the user... 35782 callback(obj); 35783 } 35784 }); 35785 } 35786 35787 function _getOdataUrl() { 35788 //url will look like this http://ugc.agilitycms.com/Agility-UGC-API-JSONP.svc 35789 //needs to be transformed to this http://ugc.agilitycms.com/Agility-UGC-API-ODATA.svc 35790 var url = API.APIUrl; 35791 url = url.substring(0, url.toLowerCase().lastIndexOf("/")) + "/Agility-UGC-API-ODATA.svc"; 35792 return url; 35793 } 35794 35795 //does the error callback from OData and returns true if there was an error. 35796 function _processOdataError(data, callback) { 35797 35798 if (data != undefined && data != null) { 35799 if (data.error != undefined && data.error != null) { 35800 var message = "An error occurred."; 35801 35802 if (data.error.message != undefined && data.error.message.value != undefined) { 35803 message = data.error.message.value; 35804 } 35805 callback({ 35806 ResponseType: API.ResponseType.Error, 35807 Message: message, 35808 ResponseData: null 35809 }); 35810 return true; 35811 } 35812 } 35813 } 35814 35815 35816 API.GetMIMEtype = function (filename) { 35817 /// <summary> 35818 /// Gets the mime-type of a file based on a filename. 35819 /// </summary> 35820 /// <param name="filename" type="String">The file name (from a file upload...)</param> 35821 35822 35823 var fn = new String(filename); 35824 var fn1 = new String(); 35825 fn1 = fn.match(/[\/\\][^\/\\]*$/); 35826 if (fn1 != null && fn1.length > 0) fn = fn1 + ""; 35827 35828 fn = fn.toLowerCase(); 35829 35830 if (fn.search(/^.*\.ai$/) >= 0) { 35831 return ("application/illustrator"); 35832 } 35833 if (fn.search(/^.*\.bin$/) >= 0) { 35834 return ("application/octet-stream"); 35835 } 35836 if (fn.search(/^.*\.pdf$/) >= 0) { 35837 return ("application/pdf"); 35838 } 35839 if (fn.search(/^.*\.ps$/) >= 0) { 35840 return ("application/postscript"); 35841 } 35842 if (fn.search(/^.*\.rtf$/) >= 0) { 35843 return ("application/rtf"); 35844 } 35845 if (fn.search(/^.*\.sit$/) >= 0) { 35846 return ("application/stuffit"); 35847 } 35848 if (fn.search(/^.*\.flv$/) >= 0) { 35849 return ("video/x-flv"); 35850 } 35851 if (fn.search(/^.*\.mdb$/) >= 0) { 35852 return ("application/vnd.ms-access"); 35853 } 35854 if (fn.search(/^.*\.xls$/) >= 0) { 35855 return ("application/vnd.ms-excel"); 35856 } 35857 if (fn.search(/^.*\.ppt$/) >= 0) { 35858 return ("application/vnd.ms-powerpoint"); 35859 } 35860 if (fn.search(/^.*\.pps$/) >= 0) { 35861 return ("application/vnd.ms-powerpoint"); 35862 } 35863 if (fn.search(/^.*\.pot$/) >= 0) { 35864 return ("application/vnd.ms-powerpoint"); 35865 } 35866 if (fn.search(/^.*\.xps$/) >= 0) { 35867 return ("application/vnd.ms-xpsdocument"); 35868 } 35869 if (fn.search(/^.*\.doc$/) >= 0) { 35870 return ("application/msword"); 35871 } 35872 if (fn.search(/^.*\.7z$/) >= 0) { 35873 return ("application/x-7z-compressed"); 35874 } 35875 if (fn.search(/^.*\.torrent$/) >= 0) { 35876 return ("application/x-bittorrent"); 35877 } 35878 if (fn.search(/^.*\.tar\.gz$/) >= 0) { 35879 return ("application/x-compressed-tar"); 35880 } 35881 if (fn.search(/^.*\.tgz$/) >= 0) { 35882 return ("application/x-compressed-tar"); 35883 } 35884 if (fn.search(/^.*\.ttf$/) >= 0) { 35885 return ("application/x-font-ttf"); 35886 } 35887 if (fn.search(/^.*\.gz$/) >= 0) { 35888 return ("application/x-gzip"); 35889 } 35890 if (fn.search(/^.*\.pdf\.gz$/) >= 0) { 35891 return ("application/x-gzpdf"); 35892 } 35893 if (fn.search(/^.*\.ps\.gz$/) >= 0) { 35894 return ("application/x-gzpostscript"); 35895 } 35896 if (fn.search(/^.*\.jar$/) >= 0) { 35897 return ("application/x-java-archive"); 35898 } 35899 if (fn.search(/^.*\.js$/) >= 0) { 35900 return ("application/javascript"); 35901 } 35902 if (fn.search(/^.*\.lzh$/) >= 0) { 35903 return ("application/x-lha"); 35904 } 35905 if (fn.search(/^.*\.mkv$/) >= 0) { 35906 return ("video/x-matroska"); 35907 } 35908 if (fn.search(/^.*\.exe$/) >= 0) { 35909 return ("application/x-ms-dos-executable"); 35910 } 35911 if (fn.search(/^.*\.ogg$/) >= 0) { 35912 return ("application/ogg"); 35913 } 35914 if (fn.search(/^.*\.ogx$/) >= 0) { 35915 return ("application/ogg"); 35916 } 35917 if (fn.search(/^.*\.oga$/) >= 0) { 35918 return ("audio/ogg"); 35919 } 35920 if (fn.search(/^.*\.ogv$/) >= 0) { 35921 return ("video/ogg"); 35922 } 35923 if (fn.search(/^.*\.ogg$/) >= 0) { 35924 return ("audio/x-vorbis+ogg"); 35925 } 35926 if (fn.search(/^.*\.ogg$/) >= 0) { 35927 return ("audio/x-flac+ogg"); 35928 } 35929 if (fn.search(/^.*\.ogg$/) >= 0) { 35930 return ("audio/x-speex+ogg"); 35931 } 35932 if (fn.search(/^.*\.spx$/) >= 0) { 35933 return ("audio/x-speex"); 35934 } 35935 if (fn.search(/^.*\.ogg$/) >= 0) { 35936 return ("video/x-theora+ogg"); 35937 } 35938 if (fn.search(/^.*\.ogm$/) >= 0) { 35939 return ("video/x-ogm+ogg"); 35940 } 35941 if (fn.search(/^.*\.qtl$/) >= 0) { 35942 return ("application/x-quicktime-media-link"); 35943 } 35944 if (fn.search(/^.*\.tar$/) >= 0) { 35945 return ("application/x-tar"); 35946 } 35947 if (fn.search(/^.*\.theme$/) >= 0) { 35948 return ("application/x-theme"); 35949 } 35950 if (fn.search(/^.*\.der$/) >= 0) { 35951 return ("application/x-x509-ca-cert"); 35952 } 35953 if (fn.search(/^.*\.cer$/) >= 0) { 35954 return ("application/x-x509-ca-cert"); 35955 } 35956 if (fn.search(/^.*\.crt$/) >= 0) { 35957 return ("application/x-x509-ca-cert"); 35958 } 35959 if (fn.search(/^.*\.cert$/) >= 0) { 35960 return ("application/x-x509-ca-cert"); 35961 } 35962 if (fn.search(/^.*\.pem$/) >= 0) { 35963 return ("application/x-x509-ca-cert"); 35964 } 35965 if (fn.search(/^.*\.xhtml$/) >= 0) { 35966 return ("application/xhtml+xml"); 35967 } 35968 if (fn.search(/^.*\.zip$/) >= 0) { 35969 return ("application/zip"); 35970 } 35971 if (fn.search(/^.*\.ac3$/) >= 0) { 35972 return ("audio/ac3"); 35973 } 35974 if (fn.search(/^.*\.aiff$/) >= 0) { 35975 return ("audio/x-aiff"); 35976 } 35977 if (fn.search(/^.*\.aif$/) >= 0) { 35978 return ("audio/x-aiff"); 35979 } 35980 if (fn.search(/^.*\.aifc$/) >= 0) { 35981 return ("audio/x-aiff"); 35982 } 35983 if (fn.search(/^.*\.flac$/) >= 0) { 35984 return ("audio/x-flac"); 35985 } 35986 if (fn.search(/^.*\.mid$/) >= 0) { 35987 return ("audio/midi"); 35988 } 35989 if (fn.search(/^.*\.midi$/) >= 0) { 35990 return ("audio/midi"); 35991 } 35992 if (fn.search(/^.*\.kar$/) >= 0) { 35993 return ("audio/midi"); 35994 } 35995 if (fn.search(/^.*\.m4a$/) >= 0) { 35996 return ("audio/mp4"); 35997 } 35998 if (fn.search(/^.*\.aac$/) >= 0) { 35999 return ("audio/mp4"); 36000 } 36001 if (fn.search(/^.*\.mp4$/) >= 0) { 36002 return ("video/mp4"); 36003 } 36004 if (fn.search(/^.*\.m4v$/) >= 0) { 36005 return ("video/mp4"); 36006 } 36007 if (fn.search(/^.*\.m4b$/) >= 0) { 36008 return ("audio/x-m4b"); 36009 } 36010 if (fn.search(/^.*\.3gp$/) >= 0) { 36011 return ("video/3gpp"); 36012 } 36013 if (fn.search(/^.*\.3gpp$/) >= 0) { 36014 return ("video/3gpp"); 36015 } 36016 if (fn.search(/^.*\.amr$/) >= 0) { 36017 return ("video/3gpp"); 36018 } 36019 if (fn.search(/^.*\.mp2$/) >= 0) { 36020 return ("audio/mp2"); 36021 } 36022 if (fn.search(/^.*\.mp3$/) >= 0) { 36023 return ("audio/mpeg"); 36024 } 36025 if (fn.search(/^.*\.mpga$/) >= 0) { 36026 return ("audio/mpeg"); 36027 } 36028 if (fn.search(/^.*\.m3u$/) >= 0) { 36029 return ("audio/x-mpegurl"); 36030 } 36031 if (fn.search(/^.*\.vlc$/) >= 0) { 36032 return ("audio/x-mpegurl"); 36033 } 36034 if (fn.search(/^.*\.asx$/) >= 0) { 36035 return ("audio/x-ms-asx"); 36036 } 36037 if (fn.search(/^.*\.wax$/) >= 0) { 36038 return ("audio/x-ms-asx"); 36039 } 36040 if (fn.search(/^.*\.wvx$/) >= 0) { 36041 return ("audio/x-ms-asx"); 36042 } 36043 if (fn.search(/^.*\.wmx$/) >= 0) { 36044 return ("audio/x-ms-asx"); 36045 } 36046 if (fn.search(/^.*\.psf$/) >= 0) { 36047 return ("audio/x-psf"); 36048 } 36049 if (fn.search(/^.*\.wma$/) >= 0) { 36050 return ("audio/x-ms-wma"); 36051 } 36052 if (fn.search(/^.*\.ra$/) >= 0) { 36053 return ("audio/vnd.rn-realaudio"); 36054 } 36055 if (fn.search(/^.*\.rax$/) >= 0) { 36056 return ("audio/vnd.rn-realaudio"); 36057 } 36058 if (fn.search(/^.*\.ram$/) >= 0) { 36059 return ("application/ram"); 36060 } 36061 if (fn.search(/^.*\.rv$/) >= 0) { 36062 return ("video/vnd.rn-realvideo"); 36063 } 36064 if (fn.search(/^.*\.rvx$/) >= 0) { 36065 return ("video/vnd.rn-realvideo"); 36066 } 36067 if (fn.search(/^.*\.wav$/) >= 0) { 36068 return ("audio/x-wav"); 36069 } 36070 if (fn.search(/^.*\.bmp$/) >= 0) { 36071 return ("image/bmp"); 36072 } 36073 if (fn.search(/^.*\.wbmp$/) >= 0) { 36074 return ("image/vnd.wap.wbmp"); 36075 } 36076 if (fn.search(/^.*\.gif$/) >= 0) { 36077 return ("image/gif"); 36078 } 36079 if (fn.search(/^.*\.jpeg$/) >= 0) { 36080 return ("image/jpeg"); 36081 } 36082 if (fn.search(/^.*\.jpg$/) >= 0) { 36083 return ("image/jpeg"); 36084 } 36085 if (fn.search(/^.*\.jpe$/) >= 0) { 36086 return ("image/jpeg"); 36087 } 36088 if (fn.search(/^.*\.png$/) >= 0) { 36089 return ("image/png"); 36090 } 36091 if (fn.search(/^.*\.rle$/) >= 0) { 36092 return ("image/rle"); 36093 } 36094 if (fn.search(/^.*\.svg$/) >= 0) { 36095 return ("image/svg+xml"); 36096 } 36097 if (fn.search(/^.*\.svgz$/) >= 0) { 36098 return ("image/svg+xml-compressed"); 36099 } 36100 if (fn.search(/^.*\.tif$/) >= 0) { 36101 return ("image/tiff"); 36102 } 36103 if (fn.search(/^.*\.tiff$/) >= 0) { 36104 return ("image/tiff"); 36105 } 36106 if (fn.search(/^.*\.eps$/) >= 0) { 36107 return ("image/x-eps"); 36108 } 36109 if (fn.search(/^.*\.ico$/) >= 0) { 36110 return ("image/x-ico"); 36111 } 36112 if (fn.search(/^.*\.psd$/) >= 0) { 36113 return ("image/x-psd"); 36114 } 36115 if (fn.search(/^.*\.vcs$/) >= 0) { 36116 return ("text/calendar"); 36117 } 36118 if (fn.search(/^.*\.ics$/) >= 0) { 36119 return ("text/calendar"); 36120 } 36121 if (fn.search(/^.*\.css$/) >= 0) { 36122 return ("text/css"); 36123 } 36124 if (fn.search(/^.*\.CSSL$/) >= 0) { 36125 return ("text/css"); 36126 } 36127 if (fn.search(/^.*\.rtx$/) >= 0) { 36128 return ("text/richtext"); 36129 } 36130 if (fn.search(/^.*\.rss$/) >= 0) { 36131 return ("application/rss+xml"); 36132 } 36133 if (fn.search(/^.*\.atom$/) >= 0) { 36134 return ("application/atom+xml"); 36135 } 36136 if (fn.search(/^.*\.opml$/) >= 0) { 36137 return ("text/x-opml+xml"); 36138 } 36139 if (fn.search(/^.*\.sgml$/) >= 0) { 36140 return ("text/sgml"); 36141 } 36142 if (fn.search(/^.*\.sgm$/) >= 0) { 36143 return ("text/sgml"); 36144 } 36145 if (fn.search(/^.*\.dtd$/) >= 0) { 36146 return ("text/x-dtd"); 36147 } 36148 if (fn.search(/^.*\.html$/) >= 0) { 36149 return ("text/html"); 36150 } 36151 if (fn.search(/^.*\.htm$/) >= 0) { 36152 return ("text/html"); 36153 } 36154 if (fn.search(/^.*\.log$/) >= 0) { 36155 return ("text/x-log"); 36156 } 36157 if (fn.search(/^README*$/) >= 0) { 36158 return ("text/x-readme"); 36159 } 36160 if (fn.search(/^.*\.uri$/) >= 0) { 36161 return ("text/x-uri"); 36162 } 36163 if (fn.search(/^.*\.url$/) >= 0) { 36164 return ("text/x-uri"); 36165 } 36166 if (fn.search(/^.*\.fo$/) >= 0) { 36167 return ("text/x-xslfo"); 36168 } 36169 if (fn.search(/^.*\.xslfo$/) >= 0) { 36170 return ("text/x-xslfo"); 36171 } 36172 if (fn.search(/^.*\.xml$/) >= 0) { 36173 return ("application/xml"); 36174 } 36175 if (fn.search(/^.*\.xsl$/) >= 0) { 36176 return ("application/xml"); 36177 } 36178 if (fn.search(/^.*\.xslt$/) >= 0) { 36179 return ("application/xml"); 36180 } 36181 if (fn.search(/^.*\.xbl$/) >= 0) { 36182 return ("application/xml"); 36183 } 36184 if (fn.search(/^.*\.mpeg$/) >= 0) { 36185 return ("video/mpeg"); 36186 } 36187 if (fn.search(/^.*\.mpg$/) >= 0) { 36188 return ("video/mpeg"); 36189 } 36190 if (fn.search(/^.*\.mp2$/) >= 0) { 36191 return ("video/mpeg"); 36192 } 36193 if (fn.search(/^.*\.mpe$/) >= 0) { 36194 return ("video/mpeg"); 36195 } 36196 if (fn.search(/^.*\.vob$/) >= 0) { 36197 return ("video/mpeg"); 36198 } 36199 if (fn.search(/^.*\.m2t$/) >= 0) { 36200 return ("video/mpeg"); 36201 } 36202 if (fn.search(/^.*\.qt$/) >= 0) { 36203 return ("video/quicktime"); 36204 } 36205 if (fn.search(/^.*\.mov$/) >= 0) { 36206 return ("video/quicktime"); 36207 } 36208 if (fn.search(/^.*\.moov$/) >= 0) { 36209 return ("video/quicktime"); 36210 } 36211 if (fn.search(/^.*\.qtvr$/) >= 0) { 36212 return ("video/quicktime"); 36213 } 36214 if (fn.search(/^.*\.qtif$/) >= 0) { 36215 return ("image/x-quicktime"); 36216 } 36217 if (fn.search(/^.*\.qif$/) >= 0) { 36218 return ("image/x-quicktime"); 36219 } 36220 if (fn.search(/^.*\.viv$/) >= 0) { 36221 return ("video/vivo"); 36222 } 36223 if (fn.search(/^.*\.vivo$/) >= 0) { 36224 return ("video/vivo"); 36225 } 36226 if (fn.search(/^.*\.anim[1-9j]$/) >= 0) { 36227 return ("video/x-anim"); 36228 } 36229 if (fn.search(/^.*\.fli$/) >= 0) { 36230 return ("video/x-flic"); 36231 } 36232 if (fn.search(/^.*\.flc$/) >= 0) { 36233 return ("video/x-flic"); 36234 } 36235 if (fn.search(/^.*\.hwp$/) >= 0) { 36236 return ("application/x-hwp"); 36237 } 36238 if (fn.search(/^.*\.hwt$/) >= 0) { 36239 return ("application/x-hwt"); 36240 } 36241 if (fn.search(/^.*\.mng$/) >= 0) { 36242 return ("video/x-mng"); 36243 } 36244 if (fn.search(/^.*\.asf$/) >= 0) { 36245 return ("video/x-ms-asf"); 36246 } 36247 if (fn.search(/^.*\.nsc$/) >= 0) { 36248 return ("application/x-netshow-channel"); 36249 } 36250 if (fn.search(
36250/^.*\.wmv$/) >= 0) { 36251 return ("video/x-ms-wmv"); 36252 } 36253 if (fn.search(/^.*\.avi$/) >= 0) { 36254 return ("video/x-msvideo"); 36255 } 36256 if (fn.search(/^.*\.divx$/) >= 0) { 36257 return ("video/x-msvideo"); 36258 } 36259 return ("binary/octet-stream"); 36260 } 36261 36262 36263 36264})(Agility.UGC.API);; 36265/*! Agility CMS API 36266*/ 36267/// <reference path="Agility.js" /> 36268 36269 36270Agility.RegisterNamespace("Agility.CMS.API"); 36271 36272(function(API) { 36273 36274 //CONSTANTS 36275 API.EMPTY_GUID = "00000000-0000-0000-0000-000000000000"; 36276 36277 API.Initialized = false; 36278 36279 API.APIUrl = ""; 36280 36281 API.OnInit = function(API_Url, API_WebsiteName) { 36282 /// <summary> 36283 /// Initialize the Agility Content Server API 36284 /// </summary> 36285 /// <param name="API_Url" type="String">The URL to the Agility Server REST API.</param> 36286 /// <param name="API_WebsiteName" type="String">The Website Name.</param> 36287 36288 if (API_Url != undefined && API_Url != null) { 36289 API.APIUrl = API_Url; 36290 } 36291 API.APIWebsiteName = API_WebsiteName; 36292 API.Initialized = true; 36293 36294 } 36295 36296 36297 36298 function checkApiIntialized(callback) { 36299 36300 if (API.APIUrl == null || API.APIUrl == "" || API.APIWebsiteName == undefined) { 36301 callback({ 36302 IsError: true, 36303 Message: "The Agility CMS API has not been initialized.", 36304 ResponseData: null 36305 }); 36306 36307 return false; 36308 } 36309 36310 return true; 36311 } 36312 36313 36314 36315 36316 API.SelectContentItems = function(searchArg, hash, callback) { 36317 /// <summary> 36318 /// Get a list of content items based on a search criteria. 36319 /// </summary> 36320 /// <param name="searchArg" type="Object">Object with the following: referenceName, pageSize, rowOffset, searchFilter, sortField, sortDirection.</param> 36321 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {IsError, ResponseData, Message}.</param> 36322 /* 36323 referenceName 36324 pageSize 36325 rowOffset 36326 searchFilter 36327 sortField 36328 sortDirection 36329 */ 36330 36331 /* 36332 Filter syntax: 36333 To search for a field called "IntTest" 36334 x.xmlData.value('(CI/I/IntTest)[1]', 'int') > 1 36335 To search for Title: 36336 x.Title = 'this is a title' 36337 To search for TextBlob: 36338 x.TextBlob = 'this is a textblob' 36339 To search for state: 36340 state = 'Staging' 36341 36342 */ 36343 36344 36345 if (!checkApiIntialized(callback)) return; 36346 searchArg.hash = hash; 36347 var url = _buildAPIUrl("SelectContentItems", searchArg); 36348 36349 jQuery.getJSON(url, callback); 36350 } 36351 36352 API.GetContentItem = function(arg, hash, callback) { 36353 /// <summary> 36354 /// Get a Content Item based on its ID and Language 36355 /// </summary> 36356 /// <param name="arg" type="Function">Object with: contentID, languageCode</param> 36357 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {IsError, ResponseData, Message}.</param> 36358 36359 if (!checkApiIntialized(callback)) return; 36360 36361 /* 36362 36363 */ 36364 36365 arg.hash = hash; 36366 36367 var url = _buildAPIUrl("GetContentItem", arg); 36368 36369 jQuery.getJSON(url, callback); 36370 } 36371 36372 API.RequestApproval = function(arg, hash, callback) { 36373 /// <summary> 36374 /// Request approval for a piece of content. 36375 /// </summary> 36376 /// <param name="arg" type="Function">Object with: contentID, languageCode</param> 36377 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {IsError, ResponseData, Message}.</param> 36378 36379 if (!checkApiIntialized(callback)) return; 36380 36381 arg.hash = hash; 36382 36383 var url = _buildAPIUrl("RequestApproval",arg); 36384 jQuery.getJSON(url, callback); 36385 } 36386 36387 36388 API.GetThumbnailRootUrl = function(hash, callback) { 36389 if (!checkApiIntialized(callback)) return; 36390 36391 var arg = {hash: hash}; 36392 36393 var url = _buildAPIUrl("GetThumbnailRootUrl", arg); 36394 36395 jQuery.getJSON(url, callback); 36396 } 36397 36398 36399 API.PublishContent = function(arg, hash, callback) { 36400 /// <summary> 36401 /// Publish a piece of content. 36402 /// </summary> 36403 /// <param name="arg" type="Function">Object with: contentID, languageCode</param> 36404 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {IsError, ResponseData, Message}.</param> 36405 36406 if (!checkApiIntialized(callback)) return; 36407 36408 arg.hash = hash; 36409 36410 var url = _buildAPIUrl("PublishContent", arg); 36411 36412 jQuery.getJSON(url, callback); 36413 } 36414 36415 API.DeleteContent = function(arg, hash, callback) { 36416 /// <summary> 36417 /// Delete a piece of content. 36418 /// </summary> 36419 /// <param name="arg" type="Function">Object with: contentID, languageCode</param> 36420 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {IsError, ResponseData, Message}.</param> 36421 36422 if (!checkApiIntialized(callback)) return; 36423 36424 arg.hash = hash; 36425 36426 var url = _buildAPIUrl("DeleteContent", arg); 36427 36428 jQuery.getJSON(url, callback); 36429 } 36430 36431 API.SaveContentItem = function(arg, contentItem, attachments, hash, callback) { 36432 /// <summary> 36433 /// Saves a record type. 36434 /// </summary> 36435 /// <param name="contentID">The content ID to update (-1 if new).</param> 36436 /// <param name="contentItem">The content Item to save.</param> 36437 /// <param name="attachments">List of NEW attachments on this item (null if no new attachments).</param> 36438 /// <param name="callback" type="Function">The method to callback to. Has 1 parameter with the following object: {ResponseType, ResponseData, Message}.</param> 36439 36440 if (!checkApiIntialized(callback)) return; 36441 36442 var contentItemStr = Agility.JSON.encode(contentItem); 36443 var attachmentStr = null; 36444 if (attachments != null && attachments.length > 0) { 36445 attachmentStr = Agility.JSON.encode(attachments); 36446 } 36447 36448 arg.hash = hash; 36449 36450 var url = _buildAPIUrl("SaveContentItem", arg); 36451 36452 _submitPostData(url, {contentItem:contentItemStr, attachments:attachmentStr}, callback); 36453 } 36454 36455 function _buildAPIUrl(methodName, args) { 36456 var url = API.APIUrl; 36457 if (url == "" || url == null) return null; 36458 36459 //ensure the url ends with / 36460 if (url.lastIndexOf("/") != url.length - 1) url += "/"; 36461 36462 //create the base url for the call 36463 url += methodName + "?callback=?&website=" + escape(API.APIWebsiteName); 36464 36465 36466 for (var prop in args) { 36467 url += "&" + prop + "=" + escape(args[prop]); 36468 } 36469 36470 return url; 36471 } 36472 36473 36474 36475 function _submitPostData(url, postData, callback) { 36476 36477 //build the unique ids 36478 var uniqueID = Agility.UniqueID("postDataForm"); 36479 36480 var uniqueFormID = uniqueID + "_form"; 36481 var uniqueIFrameID = uniqueID + "_iframe"; 36482 36483 //build the return url to come back to the AgilityRedirector.htm page 36484 var returnUrl = location.href; 36485 returnUrl = returnUrl.substring(0, returnUrl.indexOf("/", returnUrl.indexOf("//") + 2)); 36486 returnUrl += Agility.ResolveUrl("~/AgilityRedirector.htm"); 36487 36488 var blankUrl = Agility.ResolveUrl("~/AgilityRedirector.htm"); 36489 36490 //remove the method callback from the url 36491 url = url.replace("?callback=?", "?returnurl=" + escape(returnUrl)); 36492 36493 //build the html for the form and iframe 36494 var formHtml = "<div id=\"" + uniqueID + "\" style='display:none'><form id=\"" + uniqueFormID + "\" method=\"post\" action=\"" + url + "\" target=\"" + uniqueIFrameID + "\">"; 36495 if (typeof postData == "string") { 36496 formHtml += "<input type=\"text\" name=\"postdata\" />"; 36497 } else { 36498 for(prop in postData) 36499 { 36500 formHtml += "<input type=\"text\" name=\""+prop+"\" />"; 36501 } 36502 } 36503 formHtml += "<input type=\"text\" name=\"url\" />"; 36504 formHtml += "</form>" 36505 formHtml += "<iframe id=\"" + uniqueIFrameID + "\" name=\"" + uniqueIFrameID + "\" src=\"" + blankUrl + "\"></iframe>"; 36506 formHtml += "</div>"; 36507 36508 36509 //add the elements to the DOM 36510 var thisBody = jQuery(document.body); 36511 jQuery(thisBody).append(formHtml); 36512 36513 //create the actual DOM elements 36514 var div = jQuery("#" + uniqueID); 36515 var form = jQuery("#" + uniqueFormID); 36516 var iframe = jQuery("#" + uniqueIFrameID); 36517 36518 if (typeof postData == "string") { 36519 $("input[name=postdata]", form).val(postData); 36520 } else { 36521 for(prop in postData) 36522 { 36523 $("input[name="+prop+"]", form).val(postData[prop]); 36524 } 36525 } 36526 36527 36528 //capture the load event of the form. 36529 jQuery(iframe).load(function() { 36530 36531 var frm = window.frames[uniqueIFrameID]; 36532 36533 var isError = true; 36534 36535 var loc = frm.location; 36536 36537 if (loc != null) { 36538 var href = loc.href; 36539 var errTest = Agility.QueryString("IsError", href); 36540 if (errTest == null) errTest = "true"; 36541 isError = errTest.toLowerCase() == "true"; 36542 } 36543 36544 36545 var data = { 36546 IsError: isError, 36547 Message: Agility.QueryString("Message", href), 36548 ResponseData: Agility.QueryString("ResponseData", href) 36549 }; 36550 36551 //call the callback 36552 setTimeout(function() { 36553 callback(data); 36554 }, 0); 36555 36556 //remove the elements... 36557 setTimeout(function() { 36558 div.empty(); 36559 }, 0); 36560 36561 }); 36562 36563 //submit the form 36564 form.submit(); 36565 } 36566 36567 36568 36569 36570 36571})(Agility.CMS.API);; 36572// -- Sammy.js -- /sammy.js 36573// http://sammyjs.org 36574// Version: 0.7.6 36575// Built: 2014-08-26 10:45:34 +0300 36576(function (factory) { if (typeof define === "function" && define.amd) { define(["jquery"], factory) } else { jQuery.sammy = window.Sammy = factory(jQuery) } })(function ($) { var Sammy, PATH_REPLACER = "([^/]+)", PATH_NAME_MATCHER = /:([\w\d]+)/g, QUERY_STRING_MATCHER = /\?([^#]*)?$/, _makeArray = function (nonarray) { return Array.prototype.slice.call(nonarray) }, _isFunction = function (obj) { return Object.prototype.toString.call(obj) === "[object Function]" }, _isArray = function (obj) { return Object.prototype.toString.call(obj) === "[object Array]" }, _isRegExp = function (obj) { return Object.prototype.toString.call(obj) === "[object RegExp]" }, _decode = function (str) { return decodeURIComponent((str || "").replace(/\+/g, " ")) }, _encode = encodeURIComponent, _escapeHTML = function (s) { return String(s).replace(/&(?!\w+;)/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """) }, _routeWrapper = function (verb) { return function () { return this.route.apply(this, [verb].concat(Array.prototype.slice.call(arguments))) } }, _template_cache = {}, _has_history = !!(window.history && history.pushState), loggers = []; Sammy = function () { var args = _makeArray(arguments), app, selector; Sammy.apps = Sammy.apps || {}; if (args.length === 0 || args[0] && _isFunction(args[0])) { return Sammy.apply(Sammy, ["body"].concat(args)) } else if (typeof (selector = args.shift()) == "string") { app = Sammy.apps[selector] || new Sammy.Application; app.element_selector = selector; if (args.length > 0) { $.each(args, function (i, plugin) { app.use(plugin) }) } if (app.element_selector != selector) { delete Sammy.apps[selector] } Sammy.apps[app.element_selector] = app; return app } }; Sammy.VERSION = "0.7.6"; Sammy.addLogger = function (logger) { loggers.push(logger) }; Sammy.log = function () { var args = _makeArray(arguments); args.unshift("[" + Date() + "]"); $.each(loggers, function (i, logger) { logger.apply(Sammy, args) }) }; if (typeof window.console != "undefined") { if (typeof window.console.log === "function" && _isFunction(window.console.log.apply)) { Sammy.addLogger(function () { window.console.log.apply(window.console, arguments) }) } else { Sammy.addLogger(function () { window.console.log(arguments) }) } } else if (typeof console != "undefined") { Sammy.addLogger(function () { console.log.apply(console, arguments) }) } $.extend(Sammy, { makeArray: _makeArray, isFunction: _isFunction, isArray: _isArray }); Sammy.Object = function (obj) { return $.extend(this, obj || {}) }; $.extend(Sammy.Object.prototype, { escapeHTML: _escapeHTML, h: _escapeHTML, toHash: function () { var json = {};
36576 $.each(this, function (k, v) { if (!_isFunction(v)) { json[k] = v } }); return json }, toHTML: function () { var display = ""; $.each(this, function (k, v) { if (!_isFunction(v)) { display += "<strong>" + k + "</strong> " + v + "<br />" } }); return display }, keys: function (attributes_only) { var keys = []; for (var property in this) { if (!_isFunction(this[property]) || !attributes_only) { keys.push(property) } } return keys }, has: function (key) { return this[key] && $.trim(this[key].toString()) !== "" }, join: function () { var args = _makeArray(arguments); var delimiter = args.shift(); return args.join(delimiter) }, log: function () { Sammy.log.apply(Sammy, arguments) }, toString: function (include_functions) { var s = []; $.each(this, function (k, v) { if (!_isFunction(v) || include_functions) { s.push('"' + k + '": ' + v.toString()) } }); return "Sammy.Object: {" + s.join(",") + "}" } }); Sammy.targetIsThisWindow = function targetIsThisWindow(event, tagName) { var targetElement = $(event.target).closest(tagName); if (targetElement.length === 0) { return true } var targetWindow = targetElement.attr("target"); if (!targetWindow || targetWindow === window.name || targetWindow === "_self") { return true } if (targetWindow === "_blank") { return false } if (targetWindow === "top" && window === window.top) { return true } return false }; Sammy.DefaultLocationProxy = function (app, run_interval_every) { this.app = app; this.is_native = false; this.has_history = _has_history; this._startPolling(run_interval_every) }; Sammy.DefaultLocationProxy.fullPath = function (location_obj) { var matches = location_obj.toString().match(/^[^#]*(#.+)$/); var hash = matches ? matches[1] : ""; return [location_obj.pathname, location_obj.search, hash].join("") }; $.extend(Sammy.DefaultLocationProxy.prototype, { bind: function () { var proxy = this, app = this.app, lp = Sammy.DefaultLocationProxy; $(window).bind("hashchange." + this.app.eventNamespace(), function (e, non_native) { if (proxy.is_native === false && !non_native) { proxy.is_native = true; window.clearInterval(lp._interval); lp._interval = null } app.trigger("location-changed") }); if (_has_history && !app.disable_push_state) { $(window).bind("popstate." + this.app.eventNamespace(), function (e) { app.trigger("location-changed") }); $(document).delegate("a", "click.history-" + this.app.eventNamespace(), function (e) { if (e.isDefaultPrevented() || e.metaKey || e.ctrlKey) { return } var full_path = lp.fullPath(this), hostname = this.hostname ? this.hostname : function (a) { var l = document.createElement("a"); l.href = a.href; return l.hostname }(this); if (hostname == window.location.hostname && app.lookupRoute("get", full_path) && Sammy.targetIsThisWindow(e, "a")) { e.preventDefault(); proxy.setLocation(full_path); return false } }) } if (!lp._bindings) { lp._bindings = 0 } lp._bindings++ }, unbind: function () { $(window).unbind("hashchange." + this.app.eventNamespace()); $(window).unbind("popstate." + this.app.eventNamespace()); $(document).undelegate("a", "click.history-" + this.app.eventNamespace()); Sammy.DefaultLocationProxy._bindings--; if (Sammy.DefaultLocationProxy._bindings <= 0) { window.clearInterval(Sammy.DefaultLocationProxy._interval); Sammy.DefaultLocationProxy._interval = null } }, getLocation: function () { return Sammy.DefaultLocationProxy.fullPath(window.location) }, setLocation: function (new_location) { if (/^([^#\/]|$)/.test(new_location)) { if (_has_history && !this.app.disable_push_state) { new_location = "/" + new_location } else { new_location = "#!/" + new_location } } if (new_location != this.getLocation()) { if (_has_history && !this.app.disable_push_state && /^\//.test(new_location)) { history.pushState({ path: new_location }, window.title, new_location); this.app.trigger("location-changed") } else { return window.location = new_location } } }, _startPolling: function (every) { var proxy = this; if (!Sammy.DefaultLocationProxy._interval) { if (!every) { every = 10 } var hashCheck = function () { var current_location = proxy.getLocation(); if (typeof Sammy.DefaultLocationProxy._last_location == "undefined" || current_location != Sammy.DefaultLocationProxy._last_location) { window.setTimeout(function () { $(window).trigger("hashchange", [true]) }, 0) } Sammy.DefaultLocationProxy._last_location = current_location }; hashCheck(); Sammy.DefaultLocationProxy._interval = window.setInterval(hashCheck, every) } } }); Sammy.Application = function (app_function) { var app = this; this.routes = {}; this.listeners = new Sammy.Object({}); this.arounds = []; this.befores = []; this.namespace = (new Date).getTime() + "-" + parseInt(Math.random() * 1e3, 10); this.context_prototype = function () { Sammy.EventContext.apply(this, arguments) }; this.context_prototype.prototype = new Sammy.EventContext; if (_isFunction(app_function)) { app_function.apply(this, [this]) } if (!this._location_proxy) { this.setLocationProxy(new Sammy.DefaultLocationProxy(this, this.run_interval_every)) } if (this.debug) { this.bindToAllEvents(function (e, data) { app.log(app.toString(), e.cleaned_type, data || {}) }) } }; Sammy.Application.prototype = $.extend({}, Sammy.Object.prototype, { ROUTE_VERBS: ["get", "post", "put", "delete"], APP_EVENTS: ["run", "unload", "lookup-route", "run-route", "route-found", "event-context-before", "event-context-after", "changed", "error", "check-form-submission", "redirect", "location-changed"], _last_route: null, _location_proxy: null, _running: false, element_selector: "body", debug: false, raise_errors: false, run_interval_every: 50, disable_push_state: false, template_engine: null, toString: function () { return "Sammy.Application:" + this.element_selector }, $element: function (selector) { return selector ? $(this.element_selector).find(selector) : $(this.element_selector) }, use: function () { var args = _makeArray(arguments), plugin = args.shift(), plugin_name = plugin || ""; try { args.unshift(this); if (typeof plugin == "string") { plugin_name = "Sammy." + plugin; plugin = Sammy[plugin] } plugin.apply(this, args) } catch (e) { if (typeof plugin === "undefined") { this.error("Plugin Error: called use() but plugin (" + plugin_name.toString() + ") is not defined", e) }
36576 else if (!_isFunction(plugin)) { this.error("Plugin Error: called use() but '" + plugin_name.toString() + "' is not a function", e) } else { this.error("Plugin Error", e) } } return this }, setLocationProxy: function (new_proxy) { var original_proxy = this._location_proxy; this._location_proxy = new_proxy; if (this.isRunning()) { if (original_proxy) { original_proxy.unbind() } this._location_proxy.bind() } }, log: function () { Sammy.log.apply(Sammy, Array.prototype.concat.apply([this.element_selector], arguments)) }, route: function (verb, path) { var app = this, param_names = [], add_route, path_match, callback = Array.prototype.slice.call(arguments, 2); if (callback.length === 0 && _isFunction(path)) { callback = [path]; path = verb; verb = "any" } verb = verb.toLowerCase(); if (path.constructor == String) { PATH_NAME_MATCHER.lastIndex = 0; while ((path_match = PATH_NAME_MATCHER.exec(path)) !== null) { param_names.push(path_match[1]) } path = new RegExp(path.replace(PATH_NAME_MATCHER, PATH_REPLACER) + "$") } $.each(callback, function (i, cb) { if (typeof cb === "string") { callback[i] = app[cb] } }); add_route = function (with_verb) { var r = { verb: with_verb, path: path, callback: callback, param_names: param_names }; app.routes[with_verb] = app.routes[with_verb] || []; app.routes[with_verb].push(r) }; if (verb === "any") { $.each(this.ROUTE_VERBS, function (i, v) { add_route(v) }) } else { add_route(verb) } return this }, get: _routeWrapper("get"), post: _routeWrapper("post"), put: _routeWrapper("put"), del: _routeWrapper("delete"), any: _routeWrapper("any"), mapRoutes: function (route_array) { var app = this; $.each(route_array, function (i, route_args) { app.route.apply(app, route_args) }); return this }, eventNamespace: function () { return ["sammy-app", this.namespace].join("-") }, bind: function (name, data, callback) { var app = this; if (typeof callback == "undefined") { callback = data } var listener_callback = function () { var e, context, data; e = arguments[0]; data = arguments[1]; if (data && data.context) { context = data.context; delete data.context } else { context = new app.context_prototype(app, "bind", e.type, data, e.target) } e.cleaned_type = e.type.replace(app.eventNamespace(), ""); callback.apply(context, [e, data]) }; if (!this.listeners[name]) { this.listeners[name] = [] } this.listeners[name].push(listener_callback); if (this.isRunning()) { this._listen(name, listener_callback) } return this }, trigger: function (name, data) { this.$element().trigger([name, this.eventNamespace()].join("."), [data]); return this }, refresh: function () { this.last_location = null; this.trigger("location-changed"); return this }, before: function (options, callback) { if (_isFunction(options)) { callback = options; options = {} } this.befores.push([options, callback]); return this }, after: function (callback) { return this.bind("event-context-after", callback) }, around: function (callback) { this.arounds.push(callback); return this }, onComplete: function (callback) { this._onComplete = callback; return this }, isRunning: function () { return this._running }, helpers: function (extensions) { $.extend(this.context_prototype.prototype, extensions); return this }, helper: function (name, method) { this.context_prototype.prototype[name] = method; return this }, run: function (start_url) { if (this.isRunning()) { return false } var app = this; $.each(this.listeners.toHash(), function (name, callbacks) { $.each(callbacks, function (i, listener_callback) { app._listen(name, listener_callback) }) }); this.trigger("run", { start_url: start_url }); this._running = true; this.last_location = null; if (!/\#(.+)/.test(this.getLocation()) && typeof start_url != "undefined") { this.setLocation(start_url) } this._checkLocation(); this._location_proxy.bind(); this.bind("location-changed", function () { app._checkLocation() }); this.bind("submit", function (e) { if (!Sammy.targetIsThisWindow(e, "form")) { return true } var returned = app._checkFormSubmission($(e.target).closest("form")); return returned === false ? e.preventDefault() : false }); $(window).bind("unload", function () { app.unload() }); return this.trigger("changed") }, unload: function () { if (!this.isRunning()) { return false } var app = this; this.trigger("unload"); this._location_proxy.unbind(); this.$element().unbind("submit").removeClass(app.eventNamespace()); $.each(this.listeners.toHash(), function (name, listeners) { $.each(listeners, function (i, listener_callback) { app._unlisten(name, listener_callback) }) }); this._running = false; return this }, destroy: function () { this.unload(); delete Sammy.apps[this.element_selector]; return this }, bindToAllEvents: function (callback) { var app = this; $.each(this.APP_EVENTS, function (i, e) { app.bind(e, callback) }); $.each(this.listeners.keys(true), function (i, name) { if ($.inArray(name, app.APP_EVENTS) == -1) { app.bind(name, callback) } }); return this }, routablePath: function (path) { return path.replace(QUERY_STRING_MATCHER, "") }, lookupRoute: function (verb, path) { var app = this, routed = false, i = 0, l, route; if (typeof this.routes[verb] != "undefined") { l = this.routes[verb].length; for (; i < l; i++) { route = this.routes[verb][i]; if (app.routablePath(path).match(route.path)) { routed = route; break } } } return routed }, runRoute: function (verb, path, params, target) { var app = this, route = this.lookupRoute(verb, path), context, wrapped_route, arounds, around, befores, before, callback_args, path_params, final_returned; if (this.debug) { this.log("runRoute", [verb, path].join(" ")) } this.trigger("run-route", { verb: verb, path: path, params: params }); if (typeof params == "undefined") { params = {} } $.extend(params, this._parseQueryString(path)); if (route) { this.trigger("route-found", { route: route });
36576 if ((path_params = route.path.exec(this.routablePath(path))) !== null) { path_params.shift(); $.each(path_params, function (i, param) { if (route.param_names[i]) { params[route.param_names[i]] = _decode(param) } else { if (!params.splat) { params.splat = [] } params.splat.push(_decode(param)) } }) } context = new this.context_prototype(this, verb, path, params, target); arounds = this.arounds.slice(0); befores = this.befores.slice(0); callback_args = [context]; if (params.splat) { callback_args = callback_args.concat(params.splat) } wrapped_route = function () { var returned, i, nextRoute; while (befores.length > 0) { before = befores.shift(); if (app.contextMatchesOptions(context, before[0])) { returned = before[1].apply(context, [context]); if (returned === false) { return false } } } app.last_route = route; context.trigger("event-context-before", { context: context }); if (typeof route.callback === "function") { route.callback = [route.callback] } if (route.callback && route.callback.length) { i = -1; nextRoute = function () { i++; if (route.callback[i]) { returned = route.callback[i].apply(context, callback_args) } else if (app._onComplete && typeof (app._onComplete === "function")) { app._onComplete(context) } }; callback_args.push(nextRoute); nextRoute() } context.trigger("event-context-after", { context: context }); return returned }; $.each(arounds.reverse(), function (i, around) { var last_wrapped_route = wrapped_route; wrapped_route = function () { return around.apply(context, [last_wrapped_route]) } }); try { final_returned = wrapped_route() } catch (e) { this.error(["500 Error", verb, path].join(" "), e) } return final_returned } else { return this.notFound(verb, path) } }, contextMatchesOptions: function (context, match_options, positive) { var options = match_options; if (typeof options === "string" || _isRegExp(options)) { options = { path: options } } if (typeof positive === "undefined") { positive = true } if ($.isEmptyObject(options)) { return true } if (_isArray(options.path)) { var results, numopt, opts, len; results = []; for (numopt = 0, len = options.path.length; numopt < len; numopt += 1) { opts = $.extend({}, options, { path: options.path[numopt] }); results.push(this.contextMatchesOptions(context, opts)) } var matched = $.inArray(true, results) > -1 ? true : false; return positive ? matched : !matched } if (options.only) { return this.contextMatchesOptions(context, options.only, true) } else if (options.except) { return this.contextMatchesOptions(context, options.except, false) } var path_matched = true, verb_matched = true; if (options.path) { if (!_isRegExp(options.path)) { options.path = new RegExp(options.path.toString() + "$") } path_matched = options.path.test(context.path) } if (options.verb) { if (typeof options.verb === "string") { verb_matched = options.verb === context.verb } else { verb_matched = options.verb.indexOf(context.verb) > -1 } } return positive ? verb_matched && path_matched : !(verb_matched && path_matched) }, getLocation: function () { return this._location_proxy.getLocation() }, setLocation: function (new_location) { return this._location_proxy.setLocation(new_location) }, swap: function (content, callback) { var $el = this.$element().html(content); if (_isFunction(callback)) { callback(content) } return $el }, templateCache: function (key, value) { if (typeof value != "undefined") { return _template_cache[key] = value } else { return _template_cache[key] } }, clearTemplateCache: function () { return _template_cache = {} }, notFound: function (verb, path) { var ret = this.error(["404 Not Found", verb, path].join(" ")); return verb === "get" ? ret : true }, error: function (message, original_error) { if (!original_error) { original_error = new Error } original_error.message = [message, original_error.message].join(" "); this.trigger("error", { message: original_error.message, error: original_error }); if (this.raise_errors) { throw original_error } else { this.log(original_error.message, original_error) } }, _checkLocation: function () { var location, returned; location = this.getLocation(); if (!this.last_location || this.last_location[0] != "get" || this.last_location[1] != location) { this.last_location = ["get", location]; returned = this.runRoute("get", location) } return returned }, _getFormVerb: function (form) { var $form = $(form), verb, $_method; $_method = $form.find('input[name="_method"]'); if ($_method.length > 0) { verb = $_method.val() } if (!verb) { verb = $form[0].getAttribute("method") } if (!verb || verb === "") { verb = "get" } return $.trim(verb.toString().toLowerCase()) }, _checkFormSubmission: function (form) { var $form, path, verb, params, returned; this.trigger("check-form-submission", { form: form }); $form = $(form); path = $form.attr("action") || ""; verb = this._getFormVerb($form); if (this.debug) { this.log("_checkFormSubmission", $form, path, verb) } if (verb === "get") { params = this._serializeFormParams($form); if (params !== "") { path += "?" + params } this.setLocation(path); returned = false } else { params = $.extend({}, this._parseFormParams($form)); returned = this.runRoute(verb, path, params, form.get(0)) } return typeof returned == "undefined" ? false : returned }, _serializeFormParams: function ($form) { var queryString = "", fields = $form.serializeArray(), i; if (fields.length > 0) { queryString = this._encodeFormPair(fields[0].name, fields[0].value); for (i = 1; i < fields.length; i++) { queryString = queryString + "&" + this._encodeFormPair(fields[i].name, fields[i].value) } } return queryString }, _encodeFormPair: function (name, value) { return _encode(name) + "=" + _encode(value) }, _parseFormParams: function ($form) { var params = {}, form_fields = $form.serializeArray(), i; for (i = 0; i < form_fields.length; i++) { params = this._parseParamPair(params, form_fields[i].name, form_fields[i].value) } return params }, _parseQueryString: function (path) { var params = {}, parts, pairs, pair, i; parts = path.match(QUERY_STRING_MATCHER); if (parts && parts[1]) { pairs = parts[1].split("&"); for (i = 0; i < pairs.length; i++) { pair = pairs[i].split("="); params = this._parseParamPair(params, _decode(pair[0]), _decode(pair[1] || "")) } } return params }, _parseParamPair: function (params, key, value) { if (typeof params[key] !== "undefined") { if (_isArray(params[key])) { params[key].push(value) } else { params[key] = [params[key], value] } } else { params[key] = value } return params }, _listen: function (name, callback) { return this.$element().bind([name, this.eventNamespace()].join("."), callback) }, _unlisten: function (name, callback) { return this.$element().unbind([name, this.eventNamespace()].join("."), callback) } }); Sammy.RenderContext = function (event_context) { this.event_context = event_c
36576ontext; this.callbacks = []; this.previous_content = null; this.content = null; this.next_engine = false; this.waiting = false }; Sammy.RenderContext.prototype = $.extend({}, Sammy.Object.prototype, { then: function (callback) { if (!_isFunction(callback)) { if (typeof callback === "string" && callback in this.event_context) { var helper = this.event_context[callback]; callback = function (content) { return helper.apply(this.event_context, [content]) } } else { return this } } var context = this; if (this.waiting) { this.callbacks.push(callback) } else { this.wait(); window.setTimeout(function () { var returned = callback.apply(context, [context.content, context.previous_content]); if (returned !== false) { context.next(returned) } }, 0) } return this }, wait: function () { this.waiting = true }, next: function (content) { this.waiting = false; if (typeof content !== "undefined") { this.previous_content = this.content; this.content = content } if (this.callbacks.length > 0) { this.then(this.callbacks.shift()) } }, load: function (location, options, callback) { var context = this; return this.then(function () { var should_cache, cached, is_json, location_array; if (_isFunction(options)) { callback = options; options = {} } else { options = $.extend({}, options) } if (callback) { this.then(callback) } if (typeof location === "string") { is_json = location.match(/\.json(\?|$)/) || options.json; should_cache = is_json ? options.cache === true : options.cache !== false; context.next_engine = context.event_context.engineFor(location); delete options.cache; delete options.json; if (options.engine) { context.next_engine = options.engine; delete options.engine } if (should_cache && (cached = this.event_context.app.templateCache(location))) { return cached } this.wait(); $.ajax($.extend({ url: location, data: {}, dataType: is_json ? "json" : "text", type: "get", success: function (data) { if (should_cache) { context.event_context.app.templateCache(location, data) } context.next(data) } }, options)); return false } else { if (location.nodeType) { return location.innerHTML } if (location.selector) { context.next_engine = location.attr("data-engine"); if (options.clone === false) { return location.remove()[0].innerHTML.toString() } else { return location[0].innerHTML.toString() } } } }) }, loadPartials: function (partials) { var name; if (partials) { this.partials = this.partials || {}; for (name in partials) { (function (context, name) { context.load(partials[name]).then(function (template) { this.partials[name] = template }) })(this, name) } } return this }, render: function (location, data, callback, partials) { if (_isFunction(location) && !data) { return this.then(location) } else { if (_isFunction(data)) { partials = callback; callback = data; data = null } else if (callback && !_isFunction(callback)) { partials = callback; callback = null } return this.loadPartials(partials).load(location).interpolate(data, location).then(callback) } }, partial: function (location, data, callback, partials) { if (_isFunction(callback)) { return this.render(location, data, partials).swap(callback) } else if (_isFunction(data)) { return this.render(location, {}, callback).swap(data) } else { return this.render(location, data, callback).swap() } }, send: function () { var context = this, args = _makeArray(arguments), fun = args.shift(); if (_isArray(args[0])) { args = args[0] } return this.then(function (content) { args.push(function (response) { context.next(response) }); context.wait(); fun.apply(fun, args); return false }) }, collect: function (array, callback, now) { var context = this; var coll = function () { if (_isFunction(array)) { callback = array; array = this.content } var contents = [], doms = false; $.each(array, function (i, item) { var returned = callback.apply(context, [i, item]); if (returned.jquery && returned.length == 1) { returned = returned[0]; doms = true } contents.push(returned); return returned }); return doms ? contents : contents.join("") }; return now ? coll() : this.then(coll) }, renderEach: function (location, name, data, callback) { if (_isArray(name)) { callback = data; data = name; name = null } return this.load(location).then(function (content) { var rctx = this; if (!data) { data = _isArray(this.previous_content) ? this.previous_content : [] } if (callback) { $.each(data, function (i, value) { var idata = {}, engine = this.next_engine || location; if (name) { idata[name] = value } else { idata = value }
36576 callback(value, rctx.event_context.interpolate(content, idata, engine)) }) } else { return this.collect(data, function (i, value) { var idata = {}, engine = this.next_engine || location; if (name) { idata[name] = value } else { idata = value } return this.event_context.interpolate(content, idata, engine) }, true) } }) }, interpolate: function (data, engine, retain) { var context = this; return this.then(function (content, prev) { if (!data && prev) { data = prev } if (this.next_engine) { engine = this.next_engine; this.next_engine = false } var rendered = context.event_context.interpolate(content, data, engine, this.partials); return retain ? prev + rendered : rendered }) }, swap: function (callback) { return this.then(function (content) { this.event_context.swap(content, callback); return content }).trigger("changed", {}) }, appendTo: function (selector) { return this.then(function (content) { $(selector).append(content) }).trigger("changed", {}) }, prependTo: function (selector) { return this.then(function (content) { $(selector).prepend(content) }).trigger("changed", {}) }, replace: function (selector) { return this.then(function (content) { $(selector).html(content) }).trigger("changed", {}) }, trigger: function (name, data) { return this.then(function (content) { if (typeof data == "undefined") { data = { content: content } } this.event_context.trigger(name, data); return content }) } }); Sammy.EventContext = function (app, verb, path, params, target) { this.app = app; this.verb = verb; this.path = path; this.params = new Sammy.Object(params); this.target = target }; Sammy.EventContext.prototype = $.extend({}, Sammy.Object.prototype, { $element: function () { return this.app.$element(_makeArray(arguments).shift()) }, engineFor: function (engine) { var context = this, engine_match; if (_isFunction(engine)) { return engine } engine = (engine || context.app.template_engine).toString(); if (engine_match = engine.match(/\.([^\.\?\#]+)(\?|$)/)) { engine = engine_match[1] } if (engine && _isFunction(context[engine])) { return context[engine] } if (context.app.template_engine) { return this.engineFor(context.app.template_engine) } return function (content, data) { return content } }, interpolate: function (content, data, engine, partials) { return this.engineFor(engine).apply(this, [content, data, partials]) }, render: function (location, data, callback, partials) { return new Sammy.RenderContext(this).render(location, data, callback, partials) }, renderEach: function (location, name, data, callback) { return new Sammy.RenderContext(this).renderEach(location, name, data, callback) }, load: function (location, options, callback) { return new Sammy.RenderContext(this).load(location, options, callback) }, loadPartials: function (partials) { return new Sammy.RenderContext(this).loadPartials(partials) }, partial: function (location, data, callback, partials) { return new Sammy.RenderContext(this).partial(location, data, callback, partials) }, send: function () { var rctx = new Sammy.RenderContext(this); return rctx.send.apply(rctx, arguments) }, redirect: function () { var to, args = _makeArray(arguments), current_location = this.app.getLocation(), l = args.length; if (l > 1) { var i = 0, paths = [], pairs = [], params = {}, has_params = false; for (; i < l; i++) { if (typeof args[i] == "string") { paths.push(args[i]) } else { $.extend(params, args[i]); has_params = true } } to = paths.join("/"); if (has_params) { for (var k in params) { pairs.push(this.app._encodeFormPair(k, params[k])) } to += "?" + pairs.join("&") } } else { to = args[0] } this.trigger("redirect", { to: to }); this.app.last_location = [this.verb, this.path]; this.app.setLocation(to); if (new RegExp(to).test(current_location)) { this.app.trigger("location-changed") } }, trigger: function (name, data) { if (typeof data == "undefined") { data = {} } if (!data.context) { data.context = this } return this.app.trigger(name, data) }, eventNamespace: function () { return this.app.eventNamespace() }, swap: function (contents, callback) { return this.app.swap(contents, callback) }, notFound: function () { return this.app.notFound(this.verb, this.path) }, json: function (string) { return $.parseJSON(string) }, toString: function () { return "Sammy.EventContext: " + [this.verb, this.path, this.params].join(" ") } }); return Sammy });; 36577/*! 36578 * Knockout JavaScript library v3.5.1 36579 * (c) The Knockout.js team - http://knockoutjs.com/ 36580 * License: MIT (http://www.opensource.org/licenses/mit-license.php) 36581 */ 36582 36583(function() {(function(n){var A=this||(0,eval)("this"),w=A.document,R=A.navigator,v=A.jQuery,H=A.JSON;
vendor: 4,182 bytes, lines 36583-36591
36583v||"undefined"===typeof jQuery||(v=jQuery);(function(n){"function"===typeof define&&define.amd?define(["exports","require"],n):"object"===typeof exports&&"object"===typeof module?n(module.exports||exports):n(A.ko={})})(function(S,T){function K(a,c){return null===a||typeof a in W?a===c:!1}function X(b,c){var d;return function(){d||(d=a.a.setTimeout(function(){d=n;b()},c))}}function Y(b,c){var d;return function(){clearTimeout(d); 36584d=a.a.setTimeout(b,c)}}function Z(a,c){c&&"change"!==c?"beforeChange"===c?this.pc(a):this.gb(a,c):this.qc(a)}function aa(a,c){null!==c&&c.s&&c.s()}function ba(a,c){var d=this.qd,e=d[r];e.ra||(this.Qb&&this.mb[c]?(d.uc(c,a,this.mb[c]),this.mb[c]=null,--this.Qb):e.I[c]||d.uc(c,a,e.J?{da:a}:d.$c(a)),a.Ja&&a.gd())}var a="undefined"!==typeof S?S:{};a.b=function(b,c){for(var d=b.split("."),e=a,f=0;f<d.length-1;f++)e=e[d[f]];e[d[d.length-1]]=c};a.L=function(a,c,d){a[c]=d};a.version="3.5.1";a.b("version", 36585a.version);a.options={deferUpdates:!1,useOnlyNativeEvents:!1,foreachHidesDestroyed:!1};a.a=function(){function b(a,b){for(var c in a)f.call(a,c)&&b(c,a[c])}function c(a,b){if(b)for(var c in b)f.call(b,c)&&(a[c]=b[c]);return a}function d(a,b){a.__proto__=b;return a}function e(b,c,d,e){var l=b[c].match(q)||[];a.a.D(d.match(q),function(b){a.a.Na(l,b,e)});b[c]=l.join(" ")}var f=Object.prototype.hasOwnProperty,g={__proto__:[]}instanceof Array,h="function"===typeof Symbol,m={},k={};m[R&&/Firefox\/2/i.test(R.userAgent)? 36586"KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];m.MouseEvents="click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" ");b(m,function(a,b){if(b.length)for(var c=0,d=b.length;c<d;c++)k[b[c]]=a});var l={propertychange:!0},p=w&&function(){for(var a=3,b=w.createElement("div"),c=b.getElementsByTagName("i");b.innerHTML="\x3c!--[if gt IE "+ ++a+"]><i></i><![endif]--\x3e",c[0];);return 4<a?a:n}(),q=/\S+/g,t;return{Jc:["authenticity_token",/^__RequestVerificationToken(_.*)?$/], 36587D:function(a,b,c){for(var d=0,e=a.length;d<e;d++)b.call(c,a[d],d,a)},A:"function"==typeof Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b)}:function(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},Lb:function(a,b,c){for(var d=0,e=a.length;d<e;d++)if(b.call(c,a[d],d,a))return a[d];return n},Pa:function(b,c){var d=a.a.A(b,c);0<d?b.splice(d,1):0===d&&b.shift()},wc:function(b){var c=[];b&&a.a.D(b,function(b){0>a.a.A(c,b)&&c.push(b)});return c},Mb:function(a, 36588b,c){var d=[];if(a)for(var e=0,l=a.length;e<l;e++)d.push(b.call(c,a[e],e));return d},jb:function(a,b,c){var d=[];if(a)for(var e=0,l=a.length;e<l;e++)b.call(c,a[e],e)&&d.push(a[e]);return d},Nb:function(a,b){if(b instanceof Array)a.push.apply(a,b);else for(var c=0,d=b.length;c<d;c++)a.push(b[c]);return a},Na:function(b,c,d){var e=a.a.A(a.a.bc(b),c);0>e?d&&b.push(c):d||b.splice(e,1)},Ba:g,extend:c,setPrototypeOf:d,Ab:g?d:c,P:b,Ga:function(a,b,c){if(!a)return a;var d={},e;for(e in a)f.call(a,e)&&(d[e]= 36589b.call(c,a[e],e,a));return d},Tb:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},Yb:function(b){b=a.a.la(b);for(var c=(b[0]&&b[0].ownerDocument||w).createElement("div"),d=0,e=b.length;d<e;d++)c.appendChild(a.oa(b[d]));return c},Ca:function(b,c){for(var d=0,e=b.length,l=[];d<e;d++){var k=b[d].cloneNode(!0);l.push(c?a.oa(k):k)}return l},va:function(b,c){a.a.Tb(b);if(c)for(var d=0,e=c.length;d<e;d++)b.appendChild(c[d])},Xc:function(b,c){var d=b.nodeType?[b]:b;if(0<d.length){for(var e=d[0], 36590l=e.parentNode,k=0,f=c.length;k<f;k++)l.insertBefore(c[k],e);k=0;for(f=d.length;k<f;k++)a.removeNode(d[k])}},Ua:function(a,b){if(a.length){for(b=8===b.nodeType&&b.parentNode||b;a.length&&a[0].parentNode!==b;)a.splice(0,1);for(;1<a.length&&a[a.length-1].parentNode!==b;)a.length--;if(1<a.length){var c=a[0],d=a[a.length-1];for(a.length=0;c!==d;)a.push(c),c=c.nextSibling;a.push(d)}}return a},Zc:function(a,b){7>p?a.setAttribute("selected",b):a.selected=b},Db:function(a){return null===a||a===n?"":a.trim? 36591a.trim():a.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")},Ud:function(a,b){a=a||"";return b.length>a.length?!1:a.substring(0,b.length)===b},vd:function(a,b){if(a===b)return!0;
vendor: 63,735 bytes, lines 36591-36715
36591if(11===a.nodeType)return!1;if(b.contains)return b.contains(1!==a.nodeType?a.parentNode:a);if(b.compareDocumentPosition)return 16==(b.compareDocumentPosition(a)&16);for(;a&&a!=b;)a=a.parentNode;return!!a},Sb:function(b){return a.a.vd(b,b.ownerDocument.documentElement)},kd:function(b){return!!a.a.Lb(b,a.a.Sb)},R:function(a){return a&& 36592a.tagName&&a.tagName.toLowerCase()},Ac:function(b){return a.onError?function(){try{return b.apply(this,arguments)}catch(c){throw a.onError&&a.onError(c),c;}}:b},setTimeout:function(b,c){return setTimeout(a.a.Ac(b),c)},Gc:function(b){setTimeout(function(){a.onError&&a.onError(b);throw b;},0)},B:function(b,c,d){var e=a.a.Ac(d);d=l[c];if(a.options.useOnlyNativeEvents||d||!v)if(d||"function"!=typeof b.addEventListener)if("undefined"!=typeof b.attachEvent){var k=function(a){e.call(b,a)},f="on"+c;b.attachEvent(f, 36593k);a.a.K.za(b,function(){b.detachEvent(f,k)})}else throw Error("Browser doesn't support addEventListener or attachEvent");else b.addEventListener(c,e,!1);else t||(t="function"==typeof v(b).on?"on":"bind"),v(b)[t](c,e)},Fb:function(b,c){if(!b||!b.nodeType)throw Error("element must be a DOM node when calling triggerEvent");var d;"input"===a.a.R(b)&&b.type&&"click"==c.toLowerCase()?(d=b.type,d="checkbox"==d||"radio"==d):d=!1;if(a.options.useOnlyNativeEvents||!v||d)if("function"==typeof w.createEvent)if("function"== 36594typeof b.dispatchEvent)d=w.createEvent(k[c]||"HTMLEvents"),d.initEvent(c,!0,!0,A,0,0,0,0,0,!1,!1,!1,!1,0,b),b.dispatchEvent(d);else throw Error("The supplied element doesn't support dispatchEvent");else if(d&&b.click)b.click();else if("undefined"!=typeof b.fireEvent)b.fireEvent("on"+c);else throw Error("Browser doesn't support triggering events");else v(b).trigger(c)},f:function(b){return a.O(b)?b():b},bc:function(b){return a.O(b)?b.v():b},Eb:function(b,c,d){var l;c&&("object"===typeof b.classList? 36595(l=b.classList[d?"add":"remove"],a.a.D(c.match(q),function(a){l.call(b.classList,a)})):"string"===typeof b.className.baseVal?e(b.className,"baseVal",c,d):e(b,"className",c,d))},Bb:function(b,c){var d=a.a.f(c);if(null===d||d===n)d="";var e=a.h.firstChild(b);!e||3!=e.nodeType||a.h.nextSibling(e)?a.h.va(b,[b.ownerDocument.createTextNode(d)]):e.data=d;a.a.Ad(b)},Yc:function(a,b){a.name=b;if(7>=p)try{var c=a.name.replace(/[&<>'"]/g,function(a){return"&#"+a.charCodeAt(0)+";"});a.mergeAttributes(w.createElement("<input name='"+ 36596c+"'/>"),!1)}catch(d){}},Ad:function(a){9<=p&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},wd:function(a){if(p){var b=a.style.width;a.style.width=0;a.style.width=b}},Pd:function(b,c){b=a.a.f(b);c=a.a.f(c);for(var d=[],e=b;e<=c;e++)d.push(e);return d},la:function(a){for(var b=[],c=0,d=a.length;c<d;c++)b.push(a[c]);return b},Da:function(a){return h?Symbol(a):a},Zd:6===p,$d:7===p,W:p,Lc:function(b,c){for(var d=a.a.la(b.getElementsByTagName("input")).concat(a.a.la(b.getElementsByTagName("textarea"))), 36597e="string"==typeof c?function(a){return a.name===c}:function(a){return c.test(a.name)},l=[],k=d.length-1;0<=k;k--)e(d[k])&&l.push(d[k]);return l},Nd:function(b){return"string"==typeof b&&(b=a.a.Db(b))?H&&H.parse?H.parse(b):(new Function("return "+b))():null},hc:function(b,c,d){if(!H||!H.stringify)throw Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js"); 36598return H.stringify(a.a.f(b),c,d)},Od:function(c,d,e){e=e||{};var l=e.params||{},k=e.includeFields||this.Jc,f=c;if("object"==typeof c&&"form"===a.a.R(c))for(var f=c.action,h=k.length-1;0<=h;h--)for(var g=a.a.Lc(c,k[h]),m=g.length-1;0<=m;m--)l[g[m].name]=g[m].value;d=a.a.f(d);var p=w.createElement("form");p.style.display="none";p.action=f;p.method="post";for(var q in d)c=w.createElement("input"),c.type="hidden",c.name=q,c.value=a.a.hc(a.a.f(d[q])),p.appendChild(c);b(l,function(a,b){var c=w.createElement("input"); 36599c.type="hidden";c.name=a;c.value=b;p.appendChild(c)});w.body.appendChild(p);e.submitter?e.submitter(p):p.submit();setTimeout(function(){p.parentNode.removeChild(p)},0)}}}();a.b("utils",a.a);a.b("utils.arrayForEach",a.a.D);a.b("utils.arrayFirst",a.a.Lb);a.b("utils.arrayFilter",a.a.jb);a.b("utils.arrayGetDistinctValues",a.a.wc);a.b("utils.arrayIndexOf",a.a.A);a.b("utils.arrayMap",a.a.Mb);a.b("utils.arrayPushAll",a.a.Nb);a.b("utils.arrayRemoveItem",a.a.Pa);a.b("utils.cloneNodes",a.a.Ca);a.b("utils.createSymbolOrString", 36600a.a.Da);a.b("utils.extend",a.a.extend);a.b("utils.fieldsIncludedWithJsonPost",a.a.Jc);a.b("utils.getFormFields",a.a.Lc);a.b("utils.objectMap",a.a.Ga);a.b("utils.peekObservable",a.a.bc);a.b("utils.postJson",a.a.Od);a.b("utils.parseJson",a.a.Nd);a.b("utils.registerEventHandler",a.a.B);a.b("utils.stringifyJson",a.a.hc);a.b("utils.range",a.a.Pd);a.b("utils.toggleDomNodeCssClass",a.a.Eb);a.b("utils.triggerEvent",a.a.Fb);a.b("utils.unwrapObservable",a.a.f);a.b("utils.objectForEach",a.a.P);a.b("utils.addOrRemoveItem", 36601a.a.Na);a.b("utils.setTextContent",a.a.Bb);a.b("unwrap",a.a.f);Function.prototype.bind||(Function.prototype.bind=function(a){var c=this;if(1===arguments.length)return function(){return c.apply(a,arguments)};var d=Array.prototype.slice.call(arguments,1);return function(){var e=d.slice(0);e.push.apply(e,arguments);return c.apply(a,e)}});a.a.g=new function(){var b=0,c="__ko__"+(new Date).getTime(),d={},e,f;a.a.W?(e=function(a,e){var f=a[c];if(!f||"null"===f||!d[f]){if(!e)return n;f=a[c]="ko"+b++;d[f]= 36602{}}return d[f]},f=function(a){var b=a[c];return b?(delete d[b],a[c]=null,!0):!1}):(e=function(a,b){var d=a[c];!d&&b&&(d=a[c]={});return d},f=function(a){return a[c]?(delete a[c],!0):!1});return{get:function(a,b){var c=e(a,!1);return c&&c[b]},set:function(a,b,c){(a=e(a,c!==n))&&(a[b]=c)},Ub:function(a,b,c){a=e(a,!0);return a[b]||(a[b]=c)},clear:f,Z:function(){return b++ +c}}};a.b("utils.domData",a.a.g);a.b("utils.domData.clear",a.a.g.clear);a.a.K=new function(){function b(b,c){var d=a.a.g.get(b,e); 36603d===n&&c&&(d=[],a.a.g.set(b,e,d));return d}function c(c){var e=b(c,!1);if(e)for(var e=e.slice(0),k=0;k<e.length;k++)e[k](c);a.a.g.clear(c);a.a.K.cleanExternalData(c);g[c.nodeType]&&d(c.childNodes,!0)}function d(b,d){for(var e=[],l,f=0;f<b.length;f++)if(!d||8===b[f].nodeType)if(c(e[e.length]=l=b[f]),b[f]!==l)for(;f--&&-1==a.a.A(e,b[f]););}var e=a.a.g.Z(),f={1:!0,8:!0,9:!0},g={1:!0,9:!0};return{za:function(a,c){if("function"!=typeof c)throw Error("Callback must be a function");b(a,!0).push(c)},yb:function(c, 36604d){var f=b(c,!1);f&&(a.a.Pa(f,d),0==f.length&&a.a.g.set(c,e,n))},oa:function(b){a.u.G(function(){f[b.nodeType]&&(c(b),g[b.nodeType]&&d(b.getElementsByTagName("*")))});return b},removeNode:function(b){a.oa(b);b.parentNode&&b.parentNode.removeChild(b)},cleanExternalData:function(a){v&&"function"==typeof v.cleanData&&v.cleanData([a])}}};a.oa=a.a.K.oa;a.removeNode=a.a.K.removeNode;a.b("cleanNode",a.oa);a.b("removeNode",a.removeNode);a.b("utils.domNodeDisposal",a.a.K);a.b("utils.domNodeDisposal.addDisposeCallback", 36605a.a.K.za);a.b("utils.domNodeDisposal.removeDisposeCallback",a.a.K.yb);(function(){var b=[0,"",""],c=[1,"<table>","</table>"],d=[3,"<table><tbody><tr>","</tr></tbody></table>"],e=[1,"<select multiple='multiple'>","</select>"],f={thead:c,tbody:c,tfoot:c,tr:[2,"<table><tbody>","</tbody></table>"],td:d,th:d,option:e,optgroup:e},g=8>=a.a.W;a.a.ua=function(c,d){var e;if(v)if(v.parseHTML)e=v.parseHTML(c,d)||[];else{if((e=v.clean([c],d))&&e[0]){for(var l=e[0];l.parentNode&&11!==l.parentNode.nodeType;)l=l.parentNode; 36606l.parentNode&&l.parentNode.removeChild(l)}}else{(e=d)||(e=w);var l=e.parentWindow||e.defaultView||A,p=a.a.Db(c).toLowerCase(),q=e.createElement("div"),t;t=(p=p.match(/^(?:\x3c!--.*?--\x3e\s*?)*?<([a-z]+)[\s>]/))&&f[p[1]]||b;p=t[0];t="ignored<div>"+t[1]+c+t[2]+"</div>";"function"==typeof l.innerShiv?q.appendChild(l.innerShiv(t)):(g&&e.body.appendChild(q),q.innerHTML=t,g&&q.parentNode.removeChild(q));for(;p--;)q=q.lastChild;e=a.a.la(q.lastChild.childNodes)}return e};a.a.Md=function(b,c){var d=a.a.ua(b, 36607c);return d.length&&d[0].parentElement||a.a.Yb(d)};a.a.fc=function(b,c){a.a.Tb(b);c=a.a.f(c);if(null!==c&&c!==n)if("string"!=typeof c&&(c=c.toString()),v)v(b).html(c);else for(var d=a.a.ua(c,b.ownerDocument),e=0;e<d.length;e++)b.appendChild(d[e])}})();a.b("utils.parseHtmlFragment",a.a.ua);a.b("utils.setHtml",a.a.fc);a.aa=function(){function b(c,e){if(c)if(8==c.nodeType){var f=a.aa.Uc(c.nodeValue);null!=f&&e.push({ud:c,Kd:f})}else if(1==c.nodeType)for(var f=0,g=c.childNodes,h=g.length;f<h;f++)b(g[f], 36608e)}var c={};return{Xb:function(a){if("function"!=typeof a)throw Error("You can only pass a function to ko.memoization.memoize()");var b=(4294967296*(1+Math.random())|0).toString(16).substring(1)+(4294967296*(1+Math.random())|0).toString(16).substring(1);c[b]=a;return"\x3c!--[ko_memo:"+b+"]--\x3e"},bd:function(a,b){var f=c[a];if(f===n)throw Error("Couldn't find any memo with ID "+a+". Perhaps it's already been unmemoized.");try{return f.apply(null,b||[]),!0}finally{delete c[a]}},cd:function(c,e){var f= 36609[];b(c,f);for(var g=0,h=f.length;g<h;g++){var m=f[g].ud,k=[m];e&&a.a.Nb(k,e);a.aa.bd(f[g].Kd,k);m.nodeValue="";m.parentNode&&m.parentNode.removeChild(m)}},Uc:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:null}}}();a.b("memoization",a.aa);a.b("memoization.memoize",a.aa.Xb);a.b("memoization.unmemoize",a.aa.bd);a.b("memoization.parseMemoText",a.aa.Uc);a.b("memoization.unmemoizeDomNodeAndDescendants",a.aa.cd);a.na=function(){function b(){if(f)for(var b=f,c=0,d;h<f;)if(d=e[h++]){if(h>b){if(5E3<= 36610++c){h=f;a.a.Gc(Error("'Too much recursion' after processing "+c+" task groups."));break}b=f}try{d()}catch(p){a.a.Gc(p)}}}function c(){b();h=f=e.length=0}var d,e=[],f=0,g=1,h=0;A.MutationObserver?d=function(a){var b=w.createElement("div");(new MutationObserver(a)).observe(b,{attributes:!0});return function(){b.classList.toggle("foo")}}(c):d=w&&"onreadystatechange"in w.createElement("script")?function(a){var b=w.createElement("script");b.onreadystatechange=function(){b.onreadystatechange=null;w.documentElement.removeChild(b); 36611b=null;a()};w.documentElement.appendChild(b)}:function(a){setTimeout(a,0)};return{scheduler:d,zb:function(b){f||a.na.scheduler(c);e[f++]=b;return g++},cancel:function(a){a=a-(g-f);a>=h&&a<f&&(e[a]=null)},resetForTesting:function(){var a=f-h;h=f=e.length=0;return a},Sd:b}}();a.b("tasks",a.na);a.b("tasks.schedule",a.na.zb);a.b("tasks.runEarly",a.na.Sd);a.Ta={throttle:function(b,c){b.throttleEvaluation=c;var d=null;return a.$({read:b,write:function(e){clearTimeout(d);d=a.a.setTimeout(function(){b(e)}, 36612c)}})},rateLimit:function(a,c){var d,e,f;"number"==typeof c?d=c:(d=c.timeout,e=c.method);a.Hb=!1;f="function"==typeof e?e:"notifyWhenChangesStop"==e?Y:X;a.ub(function(a){return f(a,d,c)})},deferred:function(b,c){if(!0!==c)throw Error("The 'deferred' extender only accepts the value 'true', because it is not supported to turn deferral off once enabled.");b.Hb||(b.Hb=!0,b.ub(function(c){var e,f=!1;return function(){if(!f){a.na.cancel(e);e=a.na.zb(c);try{f=!0,b.notifySubscribers(n,"dirty")}finally{f= 36613!1}}}}))},notify:function(a,c){a.equalityComparer="always"==c?null:K}};var W={undefined:1,"boolean":1,number:1,string:1};a.b("extenders",a.Ta);a.ic=function(b,c,d){this.da=b;this.lc=c;this.mc=d;this.Ib=!1;this.fb=this.Jb=null;a.L(this,"dispose",this.s);a.L(this,"disposeWhenNodeIsRemoved",this.l)};a.ic.prototype.s=function(){this.Ib||(this.fb&&a.a.K.yb(this.Jb,this.fb),this.Ib=!0,this.mc(),this.da=this.lc=this.mc=this.Jb=this.fb=null)};a.ic.prototype.l=function(b){this.Jb=b;a.a.K.za(b,this.fb=this.s.bind(this))}; 36614a.T=function(){a.a.Ab(this,D);D.qb(this)};var D={qb:function(a){a.U={change:[]};a.sc=1},subscribe:function(b,c,d){var e=this;d=d||"change";var f=new a.ic(e,c?b.bind(c):b,function(){a.a.Pa(e.U[d],f);e.hb&&e.hb(d)});e.Qa&&e.Qa(d);e.U[d]||(e.U[d]=[]);e.U[d].push(f);return f},notifySubscribers:function(b,c){c=c||"change";"change"===c&&this.Gb();if(this.Wa(c)){var d="change"===c&&this.ed||this.U[c].slice(0);try{a.u.xc();for(var e=0,f;f=d[e];++e)f.Ib||f.lc(b)}finally{a.u.end()}}},ob:function(){return this.sc}, 36615Dd:function(a){return this.ob()!==a},Gb:function(){++this.sc},ub:function(b){var c=this,d=a.O(c),e,f,g,h,m;c.gb||(c.gb=c.notifySubscribers,c.notifySubscribers=Z);var k=b(function(){c.Ja=!1;d&&h===c&&(h=c.nc?c.nc():c());var a=f||m&&c.sb(g,h);m=f=e=!1;a&&c.gb(g=h)});c.qc=function(a,b){b&&c.Ja||(m=!b);c.ed=c.U.change.slice(0);c.Ja=e=!0;h=a;k()};c.pc=function(a){e||(g=a,c.gb(a,"beforeChange"))};c.rc=function(){m=!0};c.gd=function(){c.sb(g,c.v(!0))&&(f=!0)}},Wa:function(a){return this.U[a]&&this.U[a].length}, 36616Bd:function(b){if(b)return this.U[b]&&this.U[b].length||0;var c=0;a.a.P(this.U,function(a,b){"dirty"!==a&&(c+=b.length)});return c},sb:function(a,c){return!this.equalityComparer||!this.equalityComparer(a,c)},toString:function(){return"[object Object]"},extend:function(b){var c=this;b&&a.a.P(b,function(b,e){var f=a.Ta[b];"function"==typeof f&&(c=f(c,e)||c)});return c}};a.L(D,"init",D.qb);a.L(D,"subscribe",D.subscribe);a.L(D,"extend",D.extend);a.L(D,"getSubscriptionsCount",D.Bd);a.a.Ba&&a.a.setPrototypeOf(D, 36617Function.prototype);a.T.fn=D;a.Qc=function(a){return null!=a&&"function"==typeof a.subscribe&&"function"==typeof a.notifySubscribers};a.b("subscribable",a.T);a.b("isSubscribable",a.Qc);a.S=a.u=function(){function b(a){d.push(e);e=a}function c(){e=d.pop()}var d=[],e,f=0;return{xc:b,end:c,cc:function(b){if(e){if(!a.Qc(b))throw Error("Only subscribable things can act as dependencies");e.od.call(e.pd,b,b.fd||(b.fd=++f))}},G:function(a,d,e){try{return b(),a.apply(d,e||[])}finally{c()}},qa:function(){if(e)return e.o.qa()}, 36618Va:function(){if(e)return e.o.Va()},Ya:function(){if(e)return e.Ya},o:function(){if(e)return e.o}}}();a.b("computedContext",a.S);a.b("computedContext.getDependenciesCount",a.S.qa);a.b("computedContext.getDependencies",a.S.Va);a.b("computedContext.isInitial",a.S.Ya);a.b("computedContext.registerDependency",a.S.cc);a.b("ignoreDependencies",a.Yd=a.u.G);var I=a.a.Da("_latestValue");a.ta=function(b){function c(){if(0<arguments.length)return c.sb(c[I],arguments[0])&&(c.ya(),c[I]=arguments[0],c.xa()),this; 36619a.u.cc(c);return c[I]}c[I]=b;a.a.Ba||a.a.extend(c,a.T.fn);a.T.fn.qb(c);a.a.Ab(c,F);a.options.deferUpdates&&a.Ta.deferred(c,!0);return c};var F={equalityComparer:K,v:function(){return this[I]},xa:function(){this.notifySubscribers(this[I],"spectate");this.notifySubscribers(this[I])},ya:function(){this.notifySubscribers(this[I],"beforeChange")}};a.a.Ba&&a.a.setPrototypeOf(F,a.T.fn);var G=a.ta.Ma="__ko_proto__";F[G]=a.ta;a.O=function(b){if((b="function"==typeof b&&b[G])&&b!==F[G]&&b!==a.o.fn[G])throw Error("Invalid object that looks like an observable; possibly from another Knockout instance"); 36620return!!b};a.Za=function(b){return"function"==typeof b&&(b[G]===F[G]||b[G]===a.o.fn[G]&&b.Nc)};a.b("observable",a.ta);a.b("isObservable",a.O);a.b("isWriteableObservable",a.Za);a.b("isWritableObservable",a.Za);a.b("observable.fn",F);a.L(F,"peek",F.v);a.L(F,"valueHasMutated",F.xa);a.L(F,"valueWillMutate",F.ya);a.Ha=function(b){b=b||[];if("object"!=typeof b||!("length"in b))throw Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");b=a.ta(b);a.a.Ab(b, 36621a.Ha.fn);return b.extend({trackArrayChanges:!0})};a.Ha.fn={remove:function(b){for(var c=this.v(),d=[],e="function"!=typeof b||a.O(b)?function(a){return a===b}:b,f=0;f<c.length;f++){var g=c[f];if(e(g)){0===d.length&&this.ya();if(c[f]!==g)throw Error("Array modified during remove; cannot remove item");d.push(g);c.splice(f,1);f--}}d.length&&this.xa();return d},removeAll:function(b){if(b===n){var c=this.v(),d=c.slice(0);this.ya();c.splice(0,c.length);this.xa();return d}return b?this.remove(function(c){return 0<= 36622a.a.A(b,c)}):[]},destroy:function(b){var c=this.v(),d="function"!=typeof b||a.O(b)?function(a){return a===b}:b;this.ya();for(var e=c.length-1;0<=e;e--){var f=c[e];d(f)&&(f._destroy=!0)}this.xa()},destroyAll:function(b){return b===n?this.destroy(function(){return!0}):b?this.destroy(function(c){return 0<=a.a.A(b,c)}):[]},indexOf:function(b){var c=this();return a.a.A(c,b)},replace:function(a,c){var d=this.indexOf(a);0<=d&&(this.ya(),this.v()[d]=c,this.xa())},sorted:function(a){var c=this().slice(0); 36623return a?c.sort(a):c.sort()},reversed:function(){return this().slice(0).reverse()}};a.a.Ba&&a.a.setPrototypeOf(a.Ha.fn,a.ta.fn);a.a.D("pop push reverse shift sort splice unshift".split(" "),function(b){a.Ha.fn[b]=function(){var a=this.v();this.ya();this.zc(a,b,arguments);var d=a[b].apply(a,arguments);this.xa();return d===a?this:d}});a.a.D(["slice"],function(b){a.Ha.fn[b]=function(){var a=this();return a[b].apply(a,arguments)}});a.Pc=function(b){return a.O(b)&&"function"==typeof b.remove&&"function"== 36624typeof b.push};a.b("observableArray",a.Ha);a.b("isObservableArray",a.Pc);a.Ta.trackArrayChanges=function(b,c){function d(){function c(){if(m){var d=[].concat(b.v()||[]),e;if(b.Wa("arrayChange")){if(!f||1<m)f=a.a.Pb(k,d,b.Ob);e=f}k=d;f=null;m=0;e&&e.length&&b.notifySubscribers(e,"arrayChange")}}e?c():(e=!0,h=b.subscribe(function(){++m},null,"spectate"),k=[].concat(b.v()||[]),f=null,g=b.subscribe(c))}b.Ob={};c&&"object"==typeof c&&a.a.extend(b.Ob,c);b.Ob.sparse=!0;if(!b.zc){var e=!1,f=null,g,h,m=0, 36625k,l=b.Qa,p=b.hb;b.Qa=function(a){l&&l.call(b,a);"arrayChange"===a&&d()};b.hb=function(a){p&&p.call(b,a);"arrayChange"!==a||b.Wa("arrayChange")||(g&&g.s(),h&&h.s(),h=g=null,e=!1,k=n)};b.zc=function(b,c,d){function l(a,b,c){return k[k.length]={status:a,value:b,index:c}}if(e&&!m){var k=[],p=b.length,g=d.length,h=0;switch(c){case "push":h=p;case "unshift":for(c=0;c<g;c++)l("added",d[c],h+c);break;case "pop":h=p-1;case "shift":p&&l("deleted",b[h],h);break;case "splice":c=Math.min(Math.max(0,0>d[0]?p+d[0]: 36626d[0]),p);for(var p=1===g?p:Math.min(c+(d[1]||0),p),g=c+g-2,h=Math.max(p,g),U=[],L=[],n=2;c<h;++c,++n)c<p&&L.push(l("deleted",b[c],c)),c<g&&U.push(l("added",d[n],c));a.a.Kc(L,U);break;default:return}f=k}}}};var r=a.a.Da("_state");a.o=a.$=function(b,c,d){function e(){if(0<arguments.length){if("function"===typeof f)f.apply(g.nb,arguments);else throw Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");return this}g.ra|| 36627a.u.cc(e);(g.ka||g.J&&e.Xa())&&e.ha();return g.X}"object"===typeof b?d=b:(d=d||{},b&&(d.read=b));if("function"!=typeof d.read)throw Error("Pass a function that returns the value of the ko.computed");var f=d.write,g={X:n,sa:!0,ka:!0,rb:!1,jc:!1,ra:!1,wb:!1,J:!1,Wc:d.read,nb:c||d.owner,l:d.disposeWhenNodeIsRemoved||d.l||null,Sa:d.disposeWhen||d.Sa,Rb:null,I:{},V:0,Ic:null};e[r]=g;e.Nc="function"===typeof f;a.a.Ba||a.a.extend(e,a.T.fn);a.T.fn.qb(e);a.a.Ab(e,C);d.pure?(g.wb=!0,g.J=!0,a.a.extend(e,da)): 36628d.deferEvaluation&&a.a.extend(e,ea);a.options.deferUpdates&&a.Ta.deferred(e,!0);g.l&&(g.jc=!0,g.l.nodeType||(g.l=null));g.J||d.deferEvaluation||e.ha();g.l&&e.ja()&&a.a.K.za(g.l,g.Rb=function(){e.s()});return e};var C={equalityComparer:K,qa:function(){return this[r].V},Va:function(){var b=[];a.a.P(this[r].I,function(a,d){b[d.Ka]=d.da});return b},Vb:function(b){if(!this[r].V)return!1;var c=this.Va();return-1!==a.a.A(c,b)?!0:!!a.a.Lb(c,function(a){return a.Vb&&a.Vb(b)})},uc:function(a,c,d){if(this[r].wb&& 36629c===this)throw Error("A 'pure' computed must not be called recursively");this[r].I[a]=d;d.Ka=this[r].V++;d.La=c.ob()},Xa:function(){var a,c,d=this[r].I;for(a in d)if(Object.prototype.hasOwnProperty.call(d,a)&&(c=d[a],this.Ia&&c.da.Ja||c.da.Dd(c.La)))return!0},Jd:function(){this.Ia&&!this[r].rb&&this.Ia(!1)},ja:function(){var a=this[r];return a.ka||0<a.V},Rd:function(){this.Ja?this[r].ka&&(this[r].sa=!0):this.Hc()},$c:function(a){if(a.Hb){var c=a.subscribe(this.Jd,this,"dirty"),d=a.subscribe(this.Rd, 36630this);return{da:a,s:function(){c.s();d.s()}}}return a.subscribe(this.Hc,this)},Hc:function(){var b=this,c=b.throttleEvaluation;c&&0<=c?(clearTimeout(this[r].Ic),this[r].Ic=a.a.setTimeout(function(){b.ha(!0)},c)):b.Ia?b.Ia(!0):b.ha(!0)},ha:function(b){var c=this[r],d=c.Sa,e=!1;if(!c.rb&&!c.ra){if(c.l&&!a.a.Sb(c.l)||d&&d()){if(!c.jc){this.s();return}}else c.jc=!1;c.rb=!0;try{e=this.zd(b)}finally{c.rb=!1}return e}},zd:function(b){var c=this[r],d=!1,e=c.wb?n:!c.V,d={qd:this,mb:c.I,Qb:c.V};a.u.xc({pd:d, 36631od:ba,o:this,Ya:e});c.I={};c.V=0;var f=this.yd(c,d);c.V?d=this.sb(c.X,f):(this.s(),d=!0);d&&(c.J?this.Gb():this.notifySubscribers(c.X,"beforeChange"),c.X=f,this.notifySubscribers(c.X,"spectate"),!c.J&&b&&this.notifySubscribers(c.X),this.rc&&this.rc());e&&this.notifySubscribers(c.X,"awake");return d},yd:function(b,c){try{var d=b.Wc;return b.nb?d.call(b.nb):d()}finally{a.u.end(),c.Qb&&!b.J&&a.a.P(c.mb,aa),b.sa=b.ka=!1}},v:function(a){var c=this[r];(c.ka&&(a||!c.V)||c.J&&this.Xa())&&this.ha();return c.X}, 36632ub:function(b){a.T.fn.ub.call(this,b);this.nc=function(){this[r].J||(this[r].sa?this.ha():this[r].ka=!1);return this[r].X};this.Ia=function(a){this.pc(this[r].X);this[r].ka=!0;a&&(this[r].sa=!0);this.qc(this,!a)}},s:function(){var b=this[r];!b.J&&b.I&&a.a.P(b.I,function(a,b){b.s&&b.s()});b.l&&b.Rb&&a.a.K.yb(b.l,b.Rb);b.I=n;b.V=0;b.ra=!0;b.sa=!1;b.ka=!1;b.J=!1;b.l=n;b.Sa=n;b.Wc=n;this.Nc||(b.nb=n)}},da={Qa:function(b){var c=this,d=c[r];if(!d.ra&&d.J&&"change"==b){d.J=!1;if(d.sa||c.Xa())d.I=null,d.V= 366330,c.ha()&&c.Gb();else{var e=[];a.a.P(d.I,function(a,b){e[b.Ka]=a});a.a.D(e,function(a,b){var e=d.I[a],m=c.$c(e.da);m.Ka=b;m.La=e.La;d.I[a]=m});c.Xa()&&c.ha()&&c.Gb()}d.ra||c.notifySubscribers(d.X,"awake")}},hb:function(b){var c=this[r];c.ra||"change"!=b||this.Wa("change")||(a.a.P(c.I,function(a,b){b.s&&(c.I[a]={da:b.da,Ka:b.Ka,La:b.La},b.s())}),c.J=!0,this.notifySubscribers(n,"asleep"))},ob:function(){var b=this[r];b.J&&(b.sa||this.Xa())&&this.ha();return a.T.fn.ob.call(this)}},ea={Qa:function(a){"change"!= 36634a&&"beforeChange"!=a||this.v()}};a.a.Ba&&a.a.setPrototypeOf(C,a.T.fn);var N=a.ta.Ma;C[N]=a.o;a.Oc=function(a){return"function"==typeof a&&a[N]===C[N]};a.Fd=function(b){return a.Oc(b)&&b[r]&&b[r].wb};a.b("computed",a.o);a.b("dependentObservable",a.o);a.b("isComputed",a.Oc);a.b("isPureComputed",a.Fd);a.b("computed.fn",C);a.L(C,"peek",C.v);a.L(C,"dispose",C.s);a.L(C,"isActive",C.ja);a.L(C,"getDependenciesCount",C.qa);a.L(C,"getDependencies",C.Va);a.xb=function(b,c){if("function"===typeof b)return a.o(b, 36635c,{pure:!0});b=a.a.extend({},b);b.pure=!0;return a.o(b,c)};a.b("pureComputed",a.xb);(function(){function b(a,f,g){g=g||new d;a=f(a);if("object"!=typeof a||null===a||a===n||a instanceof RegExp||a instanceof Date||a instanceof String||a instanceof Number||a instanceof Boolean)return a;var h=a instanceof Array?[]:{};g.save(a,h);c(a,function(c){var d=f(a[c]);switch(typeof d){case "boolean":case "number":case "string":case "function":h[c]=d;break;case "object":case "undefined":var l=g.get(d);h[c]=l!== 36636n?l:b(d,f,g)}});return h}function c(a,b){if(a instanceof Array){for(var c=0;c<a.length;c++)b(c);"function"==typeof a.toJSON&&b("toJSON")}else for(c in a)b(c)}function d(){this.keys=[];this.values=[]}a.ad=function(c){if(0==arguments.length)throw Error("When calling ko.toJS, pass the object you want to convert.");return b(c,function(b){for(var c=0;a.O(b)&&10>c;c++)b=b();return b})};a.toJSON=function(b,c,d){b=a.ad(b);return a.a.hc(b,c,d)};d.prototype={constructor:d,save:function(b,c){var d=a.a.A(this.keys, 36637b);0<=d?this.values[d]=c:(this.keys.push(b),this.values.push(c))},get:function(b){b=a.a.A(this.keys,b);return 0<=b?this.values[b]:n}}})();a.b("toJS",a.ad);a.b("toJSON",a.toJSON);a.Wd=function(b,c,d){function e(c){var e=a.xb(b,d).extend({ma:"always"}),h=e.subscribe(function(a){a&&(h.s(),c(a))});e.notifySubscribers(e.v());return h}return"function"!==typeof Promise||c?e(c.bind(d)):new Promise(e)};a.b("when",a.Wd);(function(){a.w={M:function(b){switch(a.a.R(b)){case "option":return!0===b.__ko__hasDomDataOptionValue__? 36638a.a.g.get(b,a.c.options.$b):7>=a.a.W?b.getAttributeNode("value")&&b.getAttributeNode("value").specified?b.value:b.text:b.value;case "select":return 0<=b.selectedIndex?a.w.M(b.options[b.selectedIndex]):n;default:return b.value}},cb:function(b,c,d){switch(a.a.R(b)){case "option":"string"===typeof c?(a.a.g.set(b,a.c.options.$b,n),"__ko__hasDomDataOptionValue__"in b&&delete b.__ko__hasDomDataOptionValue__,b.value=c):(a.a.g.set(b,a.c.options.$b,c),b.__ko__hasDomDataOptionValue__=!0,b.value="number"=== 36639typeof c?c:"");break;case "select":if(""===c||null===c)c=n;for(var e=-1,f=0,g=b.options.length,h;f<g;++f)if(h=a.w.M(b.options[f]),h==c||""===h&&c===n){e=f;break}if(d||0<=e||c===n&&1<b.size)b.selectedIndex=e,6===a.a.W&&a.a.setTimeout(function(){b.selectedIndex=e},0);break;default:if(null===c||c===n)c="";b.value=c}}}})();a.b("selectExtensions",a.w);a.b("selectExtensions.readValue",a.w.M);a.b("selectExtensions.writeValue",a.w.cb);a.m=function(){function b(b){b=a.a.Db(b);123===b.charCodeAt(0)&&(b=b.slice(1, 36640-1));b+="\n,";var c=[],d=b.match(e),p,q=[],h=0;if(1<d.length){for(var x=0,B;B=d[x];++x){var u=B.charCodeAt(0);if(44===u){if(0>=h){c.push(p&&q.length?{key:p,value:q.join("")}:{unknown:p||q.join("")});p=h=0;q=[];continue}}else if(58===u){if(!h&&!p&&1===q.length){p=q.pop();continue}}else if(47===u&&1<B.length&&(47===B.charCodeAt(1)||42===B.charCodeAt(1)))continue;else 47===u&&x&&1<B.length?(u=d[x-1].match(f))&&!g[u[0]]&&(b=b.substr(b.indexOf(B)+1),d=b.match(e),x=-1,B="/"):40===u||123===u||91===u?++h: 3664141===u||125===u||93===u?--h:p||q.length||34!==u&&39!==u||(B=B.slice(1,-1));q.push(B)}if(0<h)throw Error("Unbalanced parentheses, braces, or brackets");}return c}var c=["true","false","null","undefined"],d=/^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i,e=RegExp("\"(?:\\\\.|[^\"])*\"|'(?:\\\\.|[^'])*'|`(?:\\\\.|[^`])*`|/\\*(?:[^*]|\\*+[^*/])*\\*+/|//.*\n|/(?:\\\\.|[^/])+/w*|[^\\s:,/][^,\"'`{}()/:[\\]]*[^\\s,\"'`{}()/:[\\]]|[^\\s]","g"),f=/[\])"'A-Za-z0-9_$]+$/,g={"in":1,"return":1,"typeof":1}, 36642h={};return{Ra:[],wa:h,ac:b,vb:function(e,f){function l(b,e){var f;if(!x){var k=a.getBindingHandler(b);if(k&&k.preprocess&&!(e=k.preprocess(e,b,l)))return;if(k=h[b])f=e,0<=a.a.A(c,f)?f=!1:(k=f.match(d),f=null===k?!1:k[1]?"Object("+k[1]+")"+k[2]:f),k=f;k&&q.push("'"+("string"==typeof h[b]?h[b]:b)+"':function(_z){"+f+"=_z}")}g&&(e="function(){return "+e+" }");p.push("'"+b+"':"+e)}f=f||{};var p=[],q=[],g=f.valueAccessors,x=f.bindingParams,B="string"===typeof e?b(e):e;a.a.D(B,function(a){l(a.key||a.unknown, 36643a.value)});q.length&&l("_ko_property_writers","{"+q.join(",")+" }");return p.join(",")},Id:function(a,b){for(var c=0;c<a.length;c++)if(a[c].key==b)return!0;return!1},eb:function(b,c,d,e,f){if(b&&a.O(b))!a.Za(b)||f&&b.v()===e||b(e);else if((b=c.get("_ko_property_writers"))&&b[d])b[d](e)}}}();a.b("expressionRewriting",a.m);a.b("expressionRewriting.bindingRewriteValidators",a.m.Ra);a.b("expressionRewriting.parseObjectLiteral",a.m.ac);a.b("expressionRewriting.preProcessBindings",a.m.vb);a.b("expressionRewriting._twoWayBindings", 36644a.m.wa);a.b("jsonExpressionRewriting",a.m);a.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson",a.m.vb);(function(){function b(a){return 8==a.nodeType&&g.test(f?a.text:a.nodeValue)}function c(a){return 8==a.nodeType&&h.test(f?a.text:a.nodeValue)}function d(d,e){for(var f=d,h=1,g=[];f=f.nextSibling;){if(c(f)&&(a.a.g.set(f,k,!0),h--,0===h))return g;g.push(f);b(f)&&h++}if(!e)throw Error("Cannot find closing comment tag to match: "+d.nodeValue);return null}function e(a,b){var c=d(a,b);return c? 366450<c.length?c[c.length-1].nextSibling:a.nextSibling:null}var f=w&&"\x3c!--test--\x3e"===w.createComment("test").text,g=f?/^\x3c!--\s*ko(?:\s+([\s\S]+))?\s*--\x3e$/:/^\s*ko(?:\s+([\s\S]+))?\s*$/,h=f?/^\x3c!--\s*\/ko\s*--\x3e$/:/^\s*\/ko\s*$/,m={ul:!0,ol:!0},k="__ko_matchedEndComment__";a.h={ea:{},childNodes:function(a){return b(a)?d(a):a.childNodes},Ea:function(c){if(b(c)){c=a.h.childNodes(c);for(var d=0,e=c.length;d<e;d++)a.removeNode(c[d])}else a.a.Tb(c)},va:function(c,d){if(b(c)){a.h.Ea(c);for(var e= 36646c.nextSibling,f=0,k=d.length;f<k;f++)e.parentNode.insertBefore(d[f],e)}else a.a.va(c,d)},Vc:function(a,c){var d;b(a)?(d=a.nextSibling,a=a.parentNode):d=a.firstChild;d?c!==d&&a.insertBefore(c,d):a.appendChild(c)},Wb:function(c,d,e){e?(e=e.nextSibling,b(c)&&(c=c.parentNode),e?d!==e&&c.insertBefore(d,e):c.appendChild(d)):a.h.Vc(c,d)},firstChild:function(a){if(b(a))return!a.nextSibling||c(a.nextSibling)?null:a.nextSibling;if(a.firstChild&&c(a.firstChild))throw Error("Found invalid end comment, as the first child of "+ 36647a);return a.firstChild},nextSibling:function(d){b(d)&&(d=e(d));if(d.nextSibling&&c(d.nextSibling)){var f=d.nextSibling;if(c(f)&&!a.a.g.get(f,k))throw Error("Found end comment without a matching opening comment, as child of "+d);return null}return d.nextSibling},Cd:b,Vd:function(a){return(a=(f?a.text:a.nodeValue).match(g))?a[1]:null},Sc:function(d){if(m[a.a.R(d)]){var f=d.firstChild;if(f){do if(1===f.nodeType){var k;k=f.firstChild;var h=null;if(k){do if(h)h.push(k);else if(b(k)){var g=e(k,!0);g?k= 36648g:h=[k]}else c(k)&&(h=[k]);while(k=k.nextSibling)}if(k=h)for(h=f.nextSibling,g=0;g<k.length;g++)h?d.insertBefore(k[g],h):d.appendChild(k[g])}while(f=f.nextSibling)}}}}})();a.b("virtualElements",a.h);a.b("virtualElements.allowedBindings",a.h.ea);a.b("virtualElements.emptyNode",a.h.Ea);a.b("virtualElements.insertAfter",a.h.Wb);a.b("virtualElements.prepend",a.h.Vc);a.b("virtualElements.setDomNodeChildren",a.h.va);(function(){a.ga=function(){this.nd={}};a.a.extend(a.ga.prototype,{nodeHasBindings:function(b){switch(b.nodeType){case 1:return null!= 36649b.getAttribute("data-bind")||a.j.getComponentNameForNode(b);case 8:return a.h.Cd(b);default:return!1}},getBindings:function(b,c){var d=this.getBindingsString(b,c),d=d?this.parseBindingsString(d,c,b):null;return a.j.tc(d,b,c,!1)},getBindingAccessors:function(b,c){var d=this.getBindingsString(b,c),d=d?this.parseBindingsString(d,c,b,{valueAccessors:!0}):null;return a.j.tc(d,b,c,!0)},getBindingsString:function(b){switch(b.nodeType){case 1:return b.getAttribute("data-bind");case 8:return a.h.Vd(b);default:return null}}, 36650parseBindingsString:function(b,c,d,e){try{var f=this.nd,g=b+(e&&e.valueAccessors||""),h;if(!(h=f[g])){var m,k="with($context){with($data||{}){return{"+a.m.vb(b,e)+"}}}";m=new Function("$context","$element",k);h=f[g]=m}return h(c,d)}catch(l){throw l.message="Unable to parse bindings.\nBindings value: "+b+"\nMessage: "+l.message,l;}}});a.ga.instance=new a.ga})();a.b("bindingProvider",a.ga);(function(){function b(b){var c=(b=a.a.g.get(b,z))&&b.N;c&&(b.N=null,c.Tc())}function c(c,d,e){this.node=c;this.yc= 36651d;this.kb=[];this.H=!1;d.N||a.a.K.za(c,b);e&&e.N&&(e.N.kb.push(c),this.Kb=e)}function d(a){return function(){return a}}function e(a){return a()}function f(b){return a.a.Ga(a.u.G(b),function(a,c){return function(){return b()[c]}})}function g(b,c,e){return"function"===typeof b?f(b.bind(null,c,e)):a.a.Ga(b,d)}function h(a,b){return f(this.getBindings.bind(this,a,b))}function m(b,c){var d=a.h.firstChild(c);if(d){var e,f=a.ga.instance,l=f.preprocessNode;if(l){for(;e=d;)d=a.h.nextSibling(e),l.call(f,e); 36652d=a.h.firstChild(c)}for(;e=d;)d=a.h.nextSibling(e),k(b,e)}a.i.ma(c,a.i.H)}function k(b,c){var d=b,e=1===c.nodeType;e&&a.h.Sc(c);if(e||a.ga.instance.nodeHasBindings(c))d=p(c,null,b).bindingContextForDescendants;d&&!u[a.a.R(c)]&&m(d,c)}function l(b){var c=[],d={},e=[];a.a.P(b,function ca(f){if(!d[f]){var k=a.getBindingHandler(f);k&&(k.after&&(e.push(f),a.a.D(k.after,function(c){if(b[c]){if(-1!==a.a.A(e,c))throw Error("Cannot combine the following bindings, because they have a cyclic dependency: "+e.join(", ")); 36653ca(c)}}),e.length--),c.push({key:f,Mc:k}));d[f]=!0}});return c}function p(b,c,d){var f=a.a.g.Ub(b,z,{}),k=f.hd;if(!c){if(k)throw Error("You cannot apply bindings multiple times to the same element.");f.hd=!0}k||(f.context=d);f.Zb||(f.Zb={});var g;if(c&&"function"!==typeof c)g=c;else{var p=a.ga.instance,q=p.getBindingAccessors||h,m=a.$(function(){if(g=c?c(d,b):q.call(p,b,d)){if(d[t])d[t]();if(d[B])d[B]()}return g},null,{l:b});g&&m.ja()||(m=null)}var x=d,u;if(g){var J=function(){return a.a.Ga(m?m(): 36654g,e)},r=m?function(a){return function(){return e(m()[a])}}:function(a){return g[a]};J.get=function(a){return g[a]&&e(r(a))};J.has=function(a){return a in g};a.i.H in g&&a.i.subscribe(b,a.i.H,function(){var c=(0,g[a.i.H])();if(c){var d=a.h.childNodes(b);d.length&&c(d,a.Ec(d[0]))}});a.i.pa in g&&(x=a.i.Cb(b,d),a.i.subscribe(b,a.i.pa,function(){var c=(0,g[a.i.pa])();c&&a.h.firstChild(b)&&c(b)}));f=l(g);a.a.D(f,function(c){var d=c.Mc.init,e=c.Mc.update,f=c.key;if(8===b.nodeType&&!a.h.ea[f])throw Error("The binding '"+ 36655f+"' cannot be used with virtual elements");try{"function"==typeof d&&a.u.G(function(){var a=d(b,r(f),J,x.$data,x);if(a&&a.controlsDescendantBindings){if(u!==n)throw Error("Multiple bindings ("+u+" and "+f+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");u=f}}),"function"==typeof e&&a.$(function(){e(b,r(f),J,x.$data,x)},null,{l:b})}catch(k){throw k.message='Unable to process binding "'+f+": "+g[f]+'"\nMessage: '+k.message, 36656k;}})}f=u===n;return{shouldBindDescendants:f,bindingContextForDescendants:f&&x}}function q(b,c){return b&&b instanceof a.fa?b:new a.fa(b,n,n,c)}var t=a.a.Da("_subscribable"),x=a.a.Da("_ancestorBindingInfo"),B=a.a.Da("_dataDependency");a.c={};var u={script:!0,textarea:!0,template:!0};a.getBindingHandler=function(b){return a.c[b]};var J={};a.fa=function(b,c,d,e,f){function k(){var b=p?h():h,f=a.a.f(b);c?(a.a.extend(l,c),x in c&&(l[x]=c[x])):(l.$parents=[],l.$root=f,l.ko=a);l[t]=q;g?f=l.$data:(l.$rawData= 36657b,l.$data=f);d&&(l[d]=f);e&&e(l,c,f);if(c&&c[t]&&!a.S.o().Vb(c[t]))c[t]();m&&(l[B]=m);return l.$data}var l=this,g=b===J,h=g?n:b,p="function"==typeof h&&!a.O(h),q,m=f&&f.dataDependency;f&&f.exportDependencies?k():(q=a.xb(k),q.v(),q.ja()?q.equalityComparer=null:l[t]=n)};a.fa.prototype.createChildContext=function(b,c,d,e){!e&&c&&"object"==typeof c&&(e=c,c=e.as,d=e.extend);if(c&&e&&e.noChildContext){var f="function"==typeof b&&!a.O(b);return new a.fa(J,this,null,function(a){d&&d(a);a[c]=f?b():b},e)}return new a.fa(b, 36658this,c,function(a,b){a.$parentContext=b;a.$parent=b.$data;a.$parents=(b.$parents||[]).slice(0);a.$parents.unshift(a.$parent);d&&d(a)},e)};a.fa.prototype.extend=function(b,c){return new a.fa(J,this,null,function(c){a.a.extend(c,"function"==typeof b?b(c):b)},c)};var z=a.a.g.Z();c.prototype.Tc=function(){this.Kb&&this.Kb.N&&this.Kb.N.sd(this.node)};c.prototype.sd=function(b){a.a.Pa(this.kb,b);!this.kb.length&&this.H&&this.Cc()};c.prototype.Cc=function(){this.H=!0;this.yc.N&&!this.kb.length&&(this.yc.N= 36659null,a.a.K.yb(this.node,b),a.i.ma(this.node,a.i.pa),this.Tc())};a.i={H:"childrenComplete",pa:"descendantsComplete",subscribe:function(b,c,d,e,f){var k=a.a.g.Ub(b,z,{});k.Fa||(k.Fa=new a.T);f&&f.notifyImmediately&&k.Zb[c]&&a.u.G(d,e,[b]);return k.Fa.subscribe(d,e,c)},ma:function(b,c){var d=a.a.g.get(b,z);if(d&&(d.Zb[c]=!0,d.Fa&&d.Fa.notifySubscribers(b,c),c==a.i.H))if(d.N)d.N.Cc();else if(d.N===n&&d.Fa&&d.Fa.Wa(a.i.pa))throw Error("descendantsComplete event not supported for bindings on this node"); 36660},Cb:function(b,d){var e=a.a.g.Ub(b,z,{});e.N||(e.N=new c(b,e,d[x]));return d[x]==e?d:d.extend(function(a){a[x]=e})}};a.Td=function(b){return(b=a.a.g.get(b,z))&&b.context};a.ib=function(b,c,d){1===b.nodeType&&a.h.Sc(b);return p(b,c,q(d))};a.ld=function(b,c,d){d=q(d);return a.ib(b,g(c,d,b),d)};a.Oa=function(a,b){1!==b.nodeType&&8!==b.nodeType||m(q(a),b)};a.vc=function(a,b,c){!v&&A.jQuery&&(v=A.jQuery);if(2>arguments.length){if(b=w.body,!b)throw Error("ko.applyBindings: could not find document.body; has the document been loaded?"); 36661}else if(!b||1!==b.nodeType&&8!==b.nodeType)throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");k(q(a,c),b)};a.Dc=function(b){return!b||1!==b.nodeType&&8!==b.nodeType?n:a.Td(b)};a.Ec=function(b){return(b=a.Dc(b))?b.$data:n};a.b("bindingHandlers",a.c);a.b("bindingEvent",a.i);a.b("bindingEvent.subscribe",a.i.subscribe);a.b("bindingEvent.startPossiblyAsyncContentBinding",a.i.Cb);a.b("applyBindings",a.vc);a.b("applyBindingsToDescendants",a.Oa); 36662a.b("applyBindingAccessorsToNode",a.ib);a.b("applyBindingsToNode",a.ld);a.b("contextFor",a.Dc);a.b("dataFor",a.Ec)})();(function(b){function c(c,e){var k=Object.prototype.hasOwnProperty.call(f,c)?f[c]:b,l;k?k.subscribe(e):(k=f[c]=new a.T,k.subscribe(e),d(c,function(b,d){var e=!(!d||!d.synchronous);g[c]={definition:b,Gd:e};delete f[c];l||e?k.notifySubscribers(b):a.na.zb(function(){k.notifySubscribers(b)})}),l=!0)}function d(a,b){e("getConfig",[a],function(c){c?e("loadComponent",[a,c],function(a){b(a, 36663c)}):b(null,null)})}function e(c,d,f,l){l||(l=a.j.loaders.slice(0));var g=l.shift();if(g){var q=g[c];if(q){var t=!1;if(q.apply(g,d.concat(function(a){t?f(null):null!==a?f(a):e(c,d,f,l)}))!==b&&(t=!0,!g.suppressLoaderExceptions))throw Error("Component loaders must supply values by invoking the callback, not by returning values synchronously.");}else e(c,d,f,l)}else f(null)}var f={},g={};a.j={get:function(d,e){var f=Object.prototype.hasOwnProperty.call(g,d)?g[d]:b;f?f.Gd?a.u.G(function(){e(f.definition)}): 36664a.na.zb(function(){e(f.definition)}):c(d,e)},Bc:function(a){delete g[a]},oc:e};a.j.loaders=[];a.b("components",a.j);a.b("components.get",a.j.get);a.b("components.clearCachedDefinition",a.j.Bc)})();(function(){function b(b,c,d,e){function g(){0===--B&&e(h)}var h={},B=2,u=d.template;d=d.viewModel;u?f(c,u,function(c){a.j.oc("loadTemplate",[b,c],function(a){h.template=a;g()})}):g();d?f(c,d,function(c){a.j.oc("loadViewModel",[b,c],function(a){h[m]=a;g()})}):g()}function c(a,b,d){if("function"===typeof b)d(function(a){return new b(a)}); 36665else if("function"===typeof b[m])d(b[m]);else if("instance"in b){var e=b.instance;d(function(){return e})}else"viewModel"in b?c(a,b.viewModel,d):a("Unknown viewModel value: "+b)}function d(b){switch(a.a.R(b)){case "script":return a.a.ua(b.text);case "textarea":return a.a.ua(b.value);case "template":if(e(b.content))return a.a.Ca(b.content.childNodes)}return a.a.Ca(b.childNodes)}function e(a){return A.DocumentFragment?a instanceof DocumentFragment:a&&11===a.nodeType}function f(a,b,c){"string"===typeof b.require? 36666T||A.require?(T||A.require)([b.require],function(a){a&&"object"===typeof a&&a.Xd&&a["default"]&&(a=a["default"]);c(a)}):a("Uses require, but no AMD loader is present"):c(b)}function g(a){return function(b){throw Error("Component '"+a+"': "+b);}}var h={};a.j.register=function(b,c){if(!c)throw Error("Invalid configuration for "+b);if(a.j.tb(b))throw Error("Component "+b+" is already registered");h[b]=c};a.j.tb=function(a){return Object.prototype.hasOwnProperty.call(h,a)};a.j.unregister=function(b){delete h[b]; 36667a.j.Bc(b)};a.j.Fc={getConfig:function(b,c){c(a.j.tb(b)?h[b]:null)},loadComponent:function(a,c,d){var e=g(a);f(e,c,function(c){b(a,e,c,d)})},loadTemplate:function(b,c,f){b=g(b);if("string"===typeof c)f(a.a.ua(c));else if(c instanceof Array)f(c);else if(e(c))f(a.a.la(c.childNodes));else if(c.element)if(c=c.element,A.HTMLElement?c instanceof HTMLElement:c&&c.tagName&&1===c.nodeType)f(d(c));else if("string"===typeof c){var h=w.getElementById(c);h?f(d(h)):b("Cannot find element with ID "+c)}else b("Unknown element type: "+ 36668c);else b("Unknown template value: "+c)},loadViewModel:function(a,b,d){c(g(a),b,d)}};var m="createViewModel";a.b("components.register",a.j.register);a.b("components.isRegistered",a.j.tb);a.b("components.unregister",a.j.unregister);a.b("components.defaultLoader",a.j.Fc);a.j.loaders.push(a.j.Fc);a.j.dd=h})();(function(){function b(b,e){var f=b.getAttribute("params");if(f){var f=c.parseBindingsString(f,e,b,{valueAccessors:!0,bindingParams:!0}),f=a.a.Ga(f,function(c){return a.o(c,null,{l:b})}),g=a.a.Ga(f, 36669function(c){var e=c.v();return c.ja()?a.o({read:function(){return a.a.f(c())},write:a.Za(e)&&function(a){c()(a)},l:b}):e});Object.prototype.hasOwnProperty.call(g,"$raw")||(g.$raw=f);return g}return{$raw:{}}}a.j.getComponentNameForNode=function(b){var c=a.a.R(b);if(a.j.tb(c)&&(-1!=c.indexOf("-")||"[object HTMLUnknownElement]"==""+b||8>=a.a.W&&b.tagName===c))return c};a.j.tc=function(c,e,f,g){if(1===e.nodeType){var h=a.j.getComponentNameForNode(e);if(h){c=c||{};if(c.component)throw Error('Cannot use the "component" binding on a custom element matching a component'); 36670var m={name:h,params:b(e,f)};c.component=g?function(){return m}:m}}return c};var c=new a.ga;9>a.a.W&&(a.j.register=function(a){return function(b){return a.apply(this,arguments)}}(a.j.register),w.createDocumentFragment=function(b){return function(){var c=b(),f=a.j.dd,g;for(g in f);return c}}(w.createDocumentFragment))})();(function(){function b(b,c,d){c=c.template;if(!c)throw Error("Component '"+b+"' has no template");b=a.a.Ca(c);a.h.va(d,b)}function c(a,b,c){var d=a.createViewModel;return d?d.call(a, 36671b,c):b}var d=0;a.c.component={init:function(e,f,g,h,m){function k(){var a=l&&l.dispose;"function"===typeof a&&a.call(l);q&&q.s();p=l=q=null}var l,p,q,t=a.a.la(a.h.childNodes(e));a.h.Ea(e);a.a.K.za(e,k);a.o(function(){var g=a.a.f(f()),h,u;"string"===typeof g?h=g:(h=a.a.f(g.name),u=a.a.f(g.params));if(!h)throw Error("No component name specified");var n=a.i.Cb(e,m),z=p=++d;a.j.get(h,function(d){if(p===z){k();if(!d)throw Error("Unknown component '"+h+"'");b(h,d,e);var f=c(d,u,{element:e,templateNodes:t}); 36672d=n.createChildContext(f,{extend:function(a){a.$component=f;a.$componentTemplateNodes=t}});f&&f.koDescendantsComplete&&(q=a.i.subscribe(e,a.i.pa,f.koDescendantsComplete,f));l=f;a.Oa(d,e)}})},null,{l:e});return{controlsDescendantBindings:!0}}};a.h.ea.component=!0})();var V={"class":"className","for":"htmlFor"};a.c.attr={update:function(b,c){var d=a.a.f(c())||{};a.a.P(d,function(c,d){d=a.a.f(d);var g=c.indexOf(":"),g="lookupNamespaceURI"in b&&0<g&&b.lookupNamespaceURI(c.substr(0,g)),h=!1===d||null=== 36673d||d===n;h?g?b.removeAttributeNS(g,c):b.removeAttribute(c):d=d.toString();8>=a.a.W&&c in V?(c=V[c],h?b.removeAttribute(c):b[c]=d):h||(g?b.setAttributeNS(g,c,d):b.setAttribute(c,d));"name"===c&&a.a.Yc(b,h?"":d)})}};(function(){a.c.checked={after:["value","attr"],init:function(b,c,d){function e(){var e=b.checked,f=g();if(!a.S.Ya()&&(e||!m&&!a.S.qa())){var k=a.u.G(c);if(l){var q=p?k.v():k,z=t;t=f;z!==f?e&&(a.a.Na(q,f,!0),a.a.Na(q,z,!1)):a.a.Na(q,f,e);p&&a.Za(k)&&k(q)}else h&&(f===n?f=e:e||(f=n)),a.m.eb(k, 36674d,"checked",f,!0)}}function f(){var d=a.a.f(c()),e=g();l?(b.checked=0<=a.a.A(d,e),t=e):b.checked=h&&e===n?!!d:g()===d}var g=a.xb(function(){if(d.has("checkedValue"))return a.a.f(d.get("checkedValue"));if(q)return d.has("value")?a.a.f(d.get("value")):b.value}),h="checkbox"==b.type,m="radio"==b.type;if(h||m){var k=c(),l=h&&a.a.f(k)instanceof Array,p=!(l&&k.push&&k.splice),q=m||l,t=l?g():n;m&&!b.name&&a.c.uniqueName.init(b,function(){return!0});a.o(e,null,{l:b});a.a.B(b,"click",e);a.o(f,null,{l:b}); 36675k=n}}};a.m.wa.checked=!0;a.c.checkedValue={update:function(b,c){b.value=a.a.f(c())}}})();a.c["class"]={update:function(b,c){var d=a.a.Db(a.a.f(c()));a.a.Eb(b,b.__ko__cssValue,!1);b.__ko__cssValue=d;a.a.Eb(b,d,!0)}};a.c.css={update:function(b,c){var d=a.a.f(c());null!==d&&"object"==typeof d?a.a.P(d,function(c,d){d=a.a.f(d);a.a.Eb(b,c,d)}):a.c["class"].update(b,c)}};a.c.enable={update:function(b,c){var d=a.a.f(c());d&&b.disabled?b.removeAttribute("disabled"):d||b.disabled||(b.disabled=!0)}};a.c.disable= 36676{update:function(b,c){a.c.enable.update(b,function(){return!a.a.f(c())})}};a.c.event={init:function(b,c,d,e,f){var g=c()||{};a.a.P(g,function(g){"string"==typeof g&&a.a.B(b,g,function(b){var k,l=c()[g];if(l){try{var p=a.a.la(arguments);e=f.$data;p.unshift(e);k=l.apply(e,p)}finally{!0!==k&&(b.preventDefault?b.preventDefault():b.returnValue=!1)}!1===d.get(g+"Bubble")&&(b.cancelBubble=!0,b.stopPropagation&&b.stopPropagation())}})})}};a.c.foreach={Rc:function(b){return function(){var c=b(),d=a.a.bc(c); 36677if(!d||"number"==typeof d.length)return{foreach:c,templateEngine:a.ba.Ma};a.a.f(c);return{foreach:d.data,as:d.as,noChildContext:d.noChildContext,includeDestroyed:d.includeDestroyed,afterAdd:d.afterAdd,beforeRemove:d.beforeRemove,afterRender:d.afterRender,beforeMove:d.beforeMove,afterMove:d.afterMove,templateEngine:a.ba.Ma}}},init:function(b,c){return a.c.template.init(b,a.c.foreach.Rc(c))},update:function(b,c,d,e,f){return a.c.template.update(b,a.c.foreach.Rc(c),d,e,f)}};a.m.Ra.foreach=!1;a.h.ea.foreach= 36678!0;a.c.hasfocus={init:function(b,c,d){function e(e){b.__ko_hasfocusUpdating=!0;var f=b.ownerDocument;if("activeElement"in f){var g;try{g=f.activeElement}catch(l){g=f.body}e=g===b}f=c();a.m.eb(f,d,"hasfocus",e,!0);b.__ko_hasfocusLastValue=e;b.__ko_hasfocusUpdating=!1}var f=e.bind(null,!0),g=e.bind(null,!1);a.a.B(b,"focus",f);a.a.B(b,"focusin",f);a.a.B(b,"blur",g);a.a.B(b,"focusout",g);b.__ko_hasfocusLastValue=!1},update:function(b,c){var d=!!a.a.f(c());b.__ko_hasfocusUpdating||b.__ko_hasfocusLastValue=== 36679d||(d?b.focus():b.blur(),!d&&b.__ko_hasfocusLastValue&&b.ownerDocument.body.focus(),a.u.G(a.a.Fb,null,[b,d?"focusin":"focusout"]))}};a.m.wa.hasfocus=!0;a.c.hasFocus=a.c.hasfocus;a.m.wa.hasFocus="hasfocus";a.c.html={init:function(){return{controlsDescendantBindings:!0}},update:function(b,c){a.a.fc(b,c())}};(function(){function b(b,d,e){a.c[b]={init:function(b,c,h,m,k){var l,p,q={},t,x,n;if(d){m=h.get("as");var u=h.get("noChildContext");n=!(m&&u);q={as:m,noChildContext:u,exportDependencies:n}}x=(t= 36680"render"==h.get("completeOn"))||h.has(a.i.pa);a.o(function(){var h=a.a.f(c()),m=!e!==!h,u=!p,r;if(n||m!==l){x&&(k=a.i.Cb(b,k));if(m){if(!d||n)q.dataDependency=a.S.o();r=d?k.createChildContext("function"==typeof h?h:c,q):a.S.qa()?k.extend(null,q):k}u&&a.S.qa()&&(p=a.a.Ca(a.h.childNodes(b),!0));m?(u||a.h.va(b,a.a.Ca(p)),a.Oa(r,b)):(a.h.Ea(b),t||a.i.ma(b,a.i.H));l=m}},null,{l:b});return{controlsDescendantBindings:!0}}};a.m.Ra[b]=!1;a.h.ea[b]=!0}b("if");b("ifnot",!1,!0);b("with",!0)})();a.c.let={init:function(b, 36681c,d,e,f){c=f.extend(c);a.Oa(c,b);return{controlsDescendantBindings:!0}}};a.h.ea.let=!0;var Q={};a.c.options={init:function(b){if("select"!==a.a.R(b))throw Error("options binding applies only to SELECT elements");for(;0<b.length;)b.remove(0);return{controlsDescendantBindings:!0}},update:function(b,c,d){function e(){return a.a.jb(b.options,function(a){return a.selected})}function f(a,b,c){var d=typeof b;return"function"==d?b(a):"string"==d?a[b]:c}function g(c,d){if(x&&l)a.i.ma(b,a.i.H);else if(t.length){var e= 366820<=a.a.A(t,a.w.M(d[0]));a.a.Zc(d[0],e);x&&!e&&a.u.G(a.a.Fb,null,[b,"change"])}}var h=b.multiple,m=0!=b.length&&h?b.scrollTop:null,k=a.a.f(c()),l=d.get("valueAllowUnset")&&d.has("value"),p=d.get("optionsIncludeDestroyed");c={};var q,t=[];l||(h?t=a.a.Mb(e(),a.w.M):0<=b.selectedIndex&&t.push(a.w.M(b.options[b.selectedIndex])));k&&("undefined"==typeof k.length&&(k=[k]),q=a.a.jb(k,function(b){return p||b===n||null===b||!a.a.f(b._destroy)}),d.has("optionsCaption")&&(k=a.a.f(d.get("optionsCaption")),null!== 36683k&&k!==n&&q.unshift(Q)));var x=!1;c.beforeRemove=function(a){b.removeChild(a)};k=g;d.has("optionsAfterRender")&&"function"==typeof d.get("optionsAfterRender")&&(k=function(b,c){g(0,c);a.u.G(d.get("optionsAfterRender"),null,[c[0],b!==Q?b:n])});a.a.ec(b,q,function(c,e,g){g.length&&(t=!l&&g[0].selected?[a.w.M(g[0])]:[],x=!0);e=b.ownerDocument.createElement("option");c===Q?(a.a.Bb(e,d.get("optionsCaption")),a.w.cb(e,n)):(g=f(c,d.get("optionsValue"),c),a.w.cb(e,a.a.f(g)),c=f(c,d.get("optionsText"),g), 36684a.a.Bb(e,c));return[e]},c,k);if(!l){var B;h?B=t.length&&e().length<t.length:B=t.length&&0<=b.selectedIndex?a.w.M(b.options[b.selectedIndex])!==t[0]:t.length||0<=b.selectedIndex;B&&a.u.G(a.a.Fb,null,[b,"change"])}(l||a.S.Ya())&&a.i.ma(b,a.i.H);a.a.wd(b);m&&20<Math.abs(m-b.scrollTop)&&(b.scrollTop=m)}};a.c.options.$b=a.a.g.Z();a.c.selectedOptions={init:function(b,c,d){function e(){var e=c(),f=[];a.a.D(b.getElementsByTagName("option"),function(b){b.selected&&f.push(a.w.M(b))});a.m.eb(e,d,"selectedOptions", 36685f)}function f(){var d=a.a.f(c()),e=b.scrollTop;d&&"number"==typeof d.length&&a.a.D(b.getElementsByTagName("option"),function(b){var c=0<=a.a.A(d,a.w.M(b));b.selected!=c&&a.a.Zc(b,c)});b.scrollTop=e}if("select"!=a.a.R(b))throw Error("selectedOptions binding applies only to SELECT elements");var g;a.i.subscribe(b,a.i.H,function(){g?e():(a.a.B(b,"change",e),g=a.o(f,null,{l:b}))},null,{notifyImmediately:!0})},update:function(){}};a.m.wa.selectedOptions=!0;a.c.style={update:function(b,c){var d=a.a.f(c()|| 36686{});a.a.P(d,function(c,d){d=a.a.f(d);if(null===d||d===n||!1===d)d="";if(v)v(b).css(c,d);else if(/^--/.test(c))b.style.setProperty(c,d);else{c=c.replace(/-(\w)/g,function(a,b){return b.toUpperCase()});var g=b.style[c];b.style[c]=d;d===g||b.style[c]!=g||isNaN(d)||(b.style[c]=d+"px")}})}};a.c.submit={init:function(b,c,d,e,f){if("function"!=typeof c())throw Error("The value for a submit binding must be a function");a.a.B(b,"submit",function(a){var d,e=c();try{d=e.call(f.$data,b)}finally{!0!==d&&(a.preventDefault? 36687a.preventDefault():a.returnValue=!1)}})}};a.c.text={init:function(){return{controlsDescendantBindings:!0}},update:function(b,c){a.a.Bb(b,c())}};a.h.ea.text=!0;(function(){if(A&&A.navigator){var b=function(a){if(a)return parseFloat(a[1])},c=A.navigator.userAgent,d,e,f,g,h;(d=A.opera&&A.opera.version&&parseInt(A.opera.version()))||(h=b(c.match(/Edge\/([^ ]+)$/)))||b(c.match(/Chrome\/([^ ]+)/))||(e=b(c.match(/Version\/([^ ]+) Safari/)))||(f=b(c.match(/Firefox\/([^ ]+)/)))||(g=a.a.W||b(c.match(/MSIE ([^ ]+)/)))|| 36688(g=b(c.match(/rv:([^ )]+)/)))}if(8<=g&&10>g)var m=a.a.g.Z(),k=a.a.g.Z(),l=function(b){var c=this.activeElement;(c=c&&a.a.g.get(c,k))&&c(b)},p=function(b,c){var d=b.ownerDocument;a.a.g.get(d,m)||(a.a.g.set(d,m,!0),a.a.B(d,"selectionchange",l));a.a.g.set(b,k,c)};a.c.textInput={init:function(b,c,k){function l(c,d){a.a.B(b,c,d)}function m(){var d=a.a.f(c());if(null===d||d===n)d="";L!==n&&d===L?a.a.setTimeout(m,4):b.value!==d&&(y=!0,b.value=d,y=!1,v=b.value)}function r(){w||(L=b.value,w=a.a.setTimeout(z, 366894))}function z(){clearTimeout(w);L=w=n;var d=b.value;v!==d&&(v=d,a.m.eb(c(),k,"textInput",d))}var v=b.value,w,L,A=9==a.a.W?r:z,y=!1;g&&l("keypress",z);11>g&&l("propertychange",function(a){y||"value"!==a.propertyName||A(a)});8==g&&(l("keyup",z),l("keydown",z));p&&(p(b,A),l("dragend",r));(!g||9<=g)&&l("input",A);5>e&&"textarea"===a.a.R(b)?(l("keydown",r),l("paste",r),l("cut",r)):11>d?l("keydown",r):4>f?(l("DOMAutoComplete",z),l("dragdrop",z),l("drop",z)):h&&"number"===b.type&&l("keydown",r);l("change", 36690z);l("blur",z);a.o(m,null,{l:b})}};a.m.wa.textInput=!0;a.c.textinput={preprocess:function(a,b,c){c("textInput",a)}}})();a.c.uniqueName={init:function(b,c){if(c()){var d="ko_unique_"+ ++a.c.uniqueName.rd;a.a.Yc(b,d)}}};a.c.uniqueName.rd=0;a.c.using={init:function(b,c,d,e,f){var g;d.has("as")&&(g={as:d.get("as"),noChildContext:d.get("noChildContext")});c=f.createChildContext(c,g);a.Oa(c,b);return{controlsDescendantBindings:!0}}};a.h.ea.using=!0;a.c.value={init:function(b,c,d){var e=a.a.R(b),f="input"== 36691e;if(!f||"checkbox"!=b.type&&"radio"!=b.type){var g=[],h=d.get("valueUpdate"),m=!1,k=null;h&&("string"==typeof h?g=[h]:g=a.a.wc(h),a.a.Pa(g,"change"));var l=function(){k=null;m=!1;var e=c(),f=a.w.M(b);a.m.eb(e,d,"value",f)};!a.a.W||!f||"text"!=b.type||"off"==b.autocomplete||b.form&&"off"==b.form.autocomplete||-1!=a.a.A(g,"propertychange")||(a.a.B(b,"propertychange",function(){m=!0}),a.a.B(b,"focus",function(){m=!1}),a.a.B(b,"blur",function(){m&&l()}));a.a.D(g,function(c){var d=l;a.a.Ud(c,"after")&& 36692(d=function(){k=a.w.M(b);a.a.setTimeout(l,0)},c=c.substring(5));a.a.B(b,c,d)});var p;p=f&&"file"==b.type?function(){var d=a.a.f(c());null===d||d===n||""===d?b.value="":a.u.G(l)}:function(){var f=a.a.f(c()),g=a.w.M(b);if(null!==k&&f===k)a.a.setTimeout(p,0);else if(f!==g||g===n)"select"===e?(g=d.get("valueAllowUnset"),a.w.cb(b,f,g),g||f===a.w.M(b)||a.u.G(l)):a.w.cb(b,f)};if("select"===e){var q;a.i.subscribe(b,a.i.H,function(){q?d.get("valueAllowUnset")?p():l():(a.a.B(b,"change",l),q=a.o(p,null,{l:b}))}, 36693null,{notifyImmediately:!0})}else a.a.B(b,"change",l),a.o(p,null,{l:b})}else a.ib(b,{checkedValue:c})},update:function(){}};a.m.wa.value=!0;a.c.visible={update:function(b,c){var d=a.a.f(c()),e="none"!=b.style.display;d&&!e?b.style.display="":!d&&e&&(b.style.display="none")}};a.c.hidden={update:function(b,c){a.c.visible.update(b,function(){return!a.a.f(c())})}};(function(b){a.c[b]={init:function(c,d,e,f,g){return a.c.event.init.call(this,c,function(){var a={};a[b]=d();return a},e,f,g)}}})("click"); 36694a.ca=function(){};a.ca.prototype.renderTemplateSource=function(){throw Error("Override renderTemplateSource");};a.ca.prototype.createJavaScriptEvaluatorBlock=function(){throw Error("Override createJavaScriptEvaluatorBlock");};a.ca.prototype.makeTemplateSource=function(b,c){if("string"==typeof b){c=c||w;var d=c.getElementById(b);if(!d)throw Error("Cannot find template with ID "+b);return new a.C.F(d)}if(1==b.nodeType||8==b.nodeType)return new a.C.ia(b);throw Error("Unknown template type: "+b);};a.ca.prototype.renderTemplate= 36695function(a,c,d,e){a=this.makeTemplateSource(a,e);return this.renderTemplateSource(a,c,d,e)};a.ca.prototype.isTemplateRewritten=function(a,c){return!1===this.allowTemplateRewriting?!0:this.makeTemplateSource(a,c).data("isRewritten")};a.ca.prototype.rewriteTemplate=function(a,c,d){a=this.makeTemplateSource(a,d);c=c(a.text());a.text(c);a.data("isRewritten",!0)};a.b("templateEngine",a.ca);a.kc=function(){function b(b,c,d,h){b=a.m.ac(b);for(var m=a.m.Ra,k=0;k<b.length;k++){var l=b[k].key;if(Object.prototype.hasOwnProperty.call(m, 36696l)){var p=m[l];if("function"===typeof p){if(l=p(b[k].value))throw Error(l);}else if(!p)throw Error("This template engine does not support the '"+l+"' binding within its templates");}}d="ko.__tr_ambtns(function($context,$element){return(function(){return{ "+a.m.vb(b,{valueAccessors:!0})+" } })()},'"+d.toLowerCase()+"')";return h.createJavaScriptEvaluatorBlock(d)+c}var c=/(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:\"[^\"]*\"|\'[^\']*\'|[^>]*))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi, 36697d=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;return{xd:function(b,c,d){c.isTemplateRewritten(b,d)||c.rewriteTemplate(b,function(b){return a.kc.Ld(b,c)},d)},Ld:function(a,f){return a.replace(c,function(a,c,d,e,l){return b(l,c,d,f)}).replace(d,function(a,c){return b(c,"\x3c!-- ko --\x3e","#comment",f)})},md:function(b,c){return a.aa.Xb(function(d,h){var m=d.nextSibling;m&&m.nodeName.toLowerCase()===c&&a.ib(m,b,h)})}}}();a.b("__tr_ambtns",a.kc.md);(function(){a.C={};a.C.F=function(b){if(this.F=b){var c= 36698a.a.R(b);this.ab="script"===c?1:"textarea"===c?2:"template"==c&&b.content&&11===b.content.nodeType?3:4}};a.C.F.prototype.text=function(){var b=1===this.ab?"text":2===this.ab?"value":"innerHTML";if(0==arguments.length)return this.F[b];var c=arguments[0];"innerHTML"===b?a.a.fc(this.F,c):this.F[b]=c};var b=a.a.g.Z()+"_";a.C.F.prototype.data=function(c){if(1===arguments.length)return a.a.g.get(this.F,b+c);a.a.g.set(this.F,b+c,arguments[1])};var c=a.a.g.Z();a.C.F.prototype.nodes=function(){var b=this.F; 36699if(0==arguments.length){var e=a.a.g.get(b,c)||{},f=e.lb||(3===this.ab?b.content:4===this.ab?b:n);if(!f||e.jd){var g=this.text();g&&g!==e.bb&&(f=a.a.Md(g,b.ownerDocument),a.a.g.set(b,c,{lb:f,bb:g,jd:!0}))}return f}e=arguments[0];this.ab!==n&&this.text("");a.a.g.set(b,c,{lb:e})};a.C.ia=function(a){this.F=a};a.C.ia.prototype=new a.C.F;a.C.ia.prototype.constructor=a.C.ia;a.C.ia.prototype.text=function(){if(0==arguments.length){var b=a.a.g.get(this.F,c)||{};b.bb===n&&b.lb&&(b.bb=b.lb.innerHTML);return b.bb}a.a.g.set(this.F, 36700c,{bb:arguments[0]})};a.b("templateSources",a.C);a.b("templateSources.domElement",a.C.F);a.b("templateSources.anonymousTemplate",a.C.ia)})();(function(){function b(b,c,d){var e;for(c=a.h.nextSibling(c);b&&(e=b)!==c;)b=a.h.nextSibling(e),d(e,b)}function c(c,d){if(c.length){var e=c[0],f=c[c.length-1],g=e.parentNode,h=a.ga.instance,m=h.preprocessNode;if(m){b(e,f,function(a,b){var c=a.previousSibling,d=m.call(h,a);d&&(a===e&&(e=d[0]||b),a===f&&(f=d[d.length-1]||c))});c.length=0;if(!e)return;e===f?c.push(e): 36701(c.push(e,f),a.a.Ua(c,g))}b(e,f,function(b){1!==b.nodeType&&8!==b.nodeType||a.vc(d,b)});b(e,f,function(b){1!==b.nodeType&&8!==b.nodeType||a.aa.cd(b,[d])});a.a.Ua(c,g)}}function d(a){return a.nodeType?a:0<a.length?a[0]:null}function e(b,e,f,h,m){m=m||{};var n=(b&&d(b)||f||{}).ownerDocument,B=m.templateEngine||g;a.kc.xd(f,B,n);f=B.renderTemplate(f,h,m,n);if("number"!=typeof f.length||0<f.length&&"number"!=typeof f[0].nodeType)throw Error("Template engine must return an array of DOM nodes");n=!1;switch(e){case "replaceChildren":a.h.va(b, 36702f);n=!0;break;case "replaceNode":a.a.Xc(b,f);n=!0;break;case "ignoreTargetNode":break;default:throw Error("Unknown renderMode: "+e);}n&&(c(f,h),m.afterRender&&a.u.G(m.afterRender,null,[f,h[m.as||"$data"]]),"replaceChildren"==e&&a.i.ma(b,a.i.H));return f}function f(b,c,d){return a.O(b)?b():"function"===typeof b?b(c,d):b}var g;a.gc=function(b){if(b!=n&&!(b instanceof a.ca))throw Error("templateEngine must inherit from ko.templateEngine");g=b};a.dc=function(b,c,h,m,t){h=h||{};if((h.templateEngine||g)== 36703n)throw Error("Set a template engine before calling renderTemplate");t=t||"replaceChildren";if(m){var x=d(m);return a.$(function(){var g=c&&c instanceof a.fa?c:new a.fa(c,null,null,null,{exportDependencies:!0}),n=f(b,g.$data,g),g=e(m,t,n,g,h);"replaceNode"==t&&(m=g,x=d(m))},null,{Sa:function(){return!x||!a.a.Sb(x)},l:x&&"replaceNode"==t?x.parentNode:x})}return a.aa.Xb(function(d){a.dc(b,c,h,d,"replaceNode")})};a.Qd=function(b,d,g,h,m){function x(b,c){a.u.G(a.a.ec,null,[h,b,u,g,r,c]);a.i.ma(h,a.i.H)} 36704function r(a,b){c(b,v);g.afterRender&&g.afterRender(b,a);v=null}function u(a,c){v=m.createChildContext(a,{as:z,noChildContext:g.noChildContext,extend:function(a){a.$index=c;z&&(a[z+"Index"]=c)}});var d=f(b,a,v);return e(h,"ignoreTargetNode",d,v,g)}var v,z=g.as,w=!1===g.includeDestroyed||a.options.foreachHidesDestroyed&&!g.includeDestroyed;if(w||g.beforeRemove||!a.Pc(d))return a.$(function(){var b=a.a.f(d)||[];"undefined"==typeof b.length&&(b=[b]);w&&(b=a.a.jb(b,function(b){return b===n||null===b|| 36705!a.a.f(b._destroy)}));x(b)},null,{l:h});x(d.v());var A=d.subscribe(function(a){x(d(),a)},null,"arrayChange");A.l(h);return A};var h=a.a.g.Z(),m=a.a.g.Z();a.c.template={init:function(b,c){var d=a.a.f(c());if("string"==typeof d||"name"in d)a.h.Ea(b);else if("nodes"in d){d=d.nodes||[];if(a.O(d))throw Error('The "nodes" option must be a plain, non-observable array.');var e=d[0]&&d[0].parentNode;e&&a.a.g.get(e,m)||(e=a.a.Yb(d),a.a.g.set(e,m,!0));(new a.C.ia(b)).nodes(e)}else if(d=a.h.childNodes(b),0<d.length)e= 36706a.a.Yb(d),(new a.C.ia(b)).nodes(e);else throw Error("Anonymous template defined, but no template content was provided");return{controlsDescendantBindings:!0}},update:function(b,c,d,e,f){var g=c();c=a.a.f(g);d=!0;e=null;"string"==typeof c?c={}:(g="name"in c?c.name:b,"if"in c&&(d=a.a.f(c["if"])),d&&"ifnot"in c&&(d=!a.a.f(c.ifnot)),d&&!g&&(d=!1));"foreach"in c?e=a.Qd(g,d&&c.foreach||[],c,b,f):d?(d=f,"data"in c&&(d=f.createChildContext(c.data,{as:c.as,noChildContext:c.noChildContext,exportDependencies:!0})), 36707e=a.dc(g,d,c,b)):a.h.Ea(b);f=e;(c=a.a.g.get(b,h))&&"function"==typeof c.s&&c.s();a.a.g.set(b,h,!f||f.ja&&!f.ja()?n:f)}};a.m.Ra.template=function(b){b=a.m.ac(b);return 1==b.length&&b[0].unknown||a.m.Id(b,"name")?null:"This template engine does not support anonymous templates nested within its templates"};a.h.ea.template=!0})();a.b("setTemplateEngine",a.gc);a.b("renderTemplate",a.dc);a.a.Kc=function(a,c,d){if(a.length&&c.length){var e,f,g,h,m;for(e=f=0;(!d||e<d)&&(h=a[f]);++f){for(g=0;m=c[g];++g)if(h.value=== 36708m.value){h.moved=m.index;m.moved=h.index;c.splice(g,1);e=g=0;break}e+=g}}};a.a.Pb=function(){function b(b,d,e,f,g){var h=Math.min,m=Math.max,k=[],l,p=b.length,q,n=d.length,r=n-p||1,v=p+n+1,u,w,z;for(l=0;l<=p;l++)for(w=u,k.push(u=[]),z=h(n,l+r),q=m(0,l-1);q<=z;q++)u[q]=q?l?b[l-1]===d[q-1]?w[q-1]:h(w[q]||v,u[q-1]||v)+1:q+1:l+1;h=[];m=[];r=[];l=p;for(q=n;l||q;)n=k[l][q]-1,q&&n===k[l][q-1]?m.push(h[h.length]={status:e,value:d[--q],index:q}):l&&n===k[l-1][q]?r.push(h[h.length]={status:f,value:b[--l],index:l}): 36709(--q,--l,g.sparse||h.push({status:"retained",value:d[q]}));a.a.Kc(r,m,!g.dontLimitMoves&&10*p);return h.reverse()}return function(a,d,e){e="boolean"===typeof e?{dontLimitMoves:e}:e||{};a=a||[];d=d||[];return a.length<d.length?b(a,d,"added","deleted",e):b(d,a,"deleted","added",e)}}();a.b("utils.compareArrays",a.a.Pb);(function(){function b(b,c,d,h,m){var k=[],l=a.$(function(){var l=c(d,m,a.a.Ua(k,b))||[];0<k.length&&(a.a.Xc(k,l),h&&a.u.G(h,null,[d,l,m]));k.length=0;a.a.Nb(k,l)},null,{l:b,Sa:function(){return!a.a.kd(k)}}); 36710return{Y:k,$:l.ja()?l:n}}var c=a.a.g.Z(),d=a.a.g.Z();a.a.ec=function(e,f,g,h,m,k){function l(b){y={Aa:b,pb:a.ta(w++)};v.push(y);r||F.push(y)}function p(b){y=t[b];w!==y.pb.v()&&D.push(y);y.pb(w++);a.a.Ua(y.Y,e);v.push(y)}function q(b,c){if(b)for(var d=0,e=c.length;d<e;d++)a.a.D(c[d].Y,function(a){b(a,d,c[d].Aa)})}f=f||[];"undefined"==typeof f.length&&(f=[f]);h=h||{};var t=a.a.g.get(e,c),r=!t,v=[],u=0,w=0,z=[],A=[],C=[],D=[],F=[],y,I=0;if(r)a.a.D(f,l);else{if(!k||t&&t._countWaitingForRemove){var E= 36711a.a.Mb(t,function(a){return a.Aa});k=a.a.Pb(E,f,{dontLimitMoves:h.dontLimitMoves,sparse:!0})}for(var E=0,G,H,K;G=k[E];E++)switch(H=G.moved,K=G.index,G.status){case "deleted":for(;u<K;)p(u++);H===n&&(y=t[u],y.$&&(y.$.s(),y.$=n),a.a.Ua(y.Y,e).length&&(h.beforeRemove&&(v.push(y),I++,y.Aa===d?y=null:C.push(y)),y&&z.push.apply(z,y.Y)));u++;break;case "added":for(;w<K;)p(u++);H!==n?(A.push(v.length),p(H)):l(G.value)}for(;w<f.length;)p(u++);v._countWaitingForRemove=I}a.a.g.set(e,c,v);q(h.beforeMove,D);a.a.D(z, 36712h.beforeRemove?a.oa:a.removeNode);var M,O,P;try{P=e.ownerDocument.activeElement}catch(N){}if(A.length)for(;(E=A.shift())!=n;){y=v[E];for(M=n;E;)if((O=v[--E].Y)&&O.length){M=O[O.length-1];break}for(f=0;u=y.Y[f];M=u,f++)a.h.Wb(e,u,M)}for(E=0;y=v[E];E++){y.Y||a.a.extend(y,b(e,g,y.Aa,m,y.pb));for(f=0;u=y.Y[f];M=u,f++)a.h.Wb(e,u,M);!y.Ed&&m&&(m(y.Aa,y.Y,y.pb),y.Ed=!0,M=y.Y[y.Y.length-1])}P&&e.ownerDocument.activeElement!=P&&P.focus();q(h.beforeRemove,C);for(E=0;E<C.length;++E)C[E].Aa=d;q(h.afterMove,D); 36713q(h.afterAdd,F)}})();a.b("utils.setDomNodeChildrenFromArrayMapping",a.a.ec);a.ba=function(){this.allowTemplateRewriting=!1};a.ba.prototype=new a.ca;a.ba.prototype.constructor=a.ba;a.ba.prototype.renderTemplateSource=function(b,c,d,e){if(c=(9>a.a.W?0:b.nodes)?b.nodes():null)return a.a.la(c.cloneNode(!0).childNodes);b=b.text();return a.a.ua(b,e)};a.ba.Ma=new a.ba;a.gc(a.ba.Ma);a.b("nativeTemplateEngine",a.ba);(function(){a.$a=function(){var a=this.Hd=function(){if(!v||!v.tmpl)return 0;try{if(0<=v.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}(); 36714this.renderTemplateSource=function(b,e,f,g){g=g||w;f=f||{};if(2>a)throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");var h=b.data("precompiled");h||(h=b.text()||"",h=v.template(null,"{{ko_with $item.koBindingContext}}"+h+"{{/ko_with}}"),b.data("precompiled",h));b=[e.$data];e=v.extend({koBindingContext:e},f.templateOptions);e=v.tmpl(h,b,e);e.appendTo(g.createElement("div"));v.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+ 36715a+" })()) }}"};this.addTemplate=function(a,b){w.write("<script type='text/html' id='"+a+"'>"+b+"\x3c/script>")};0<a&&(v.tmpl.tag.ko_code={open:"__.push($1 || '');"}
36715,v.tmpl.tag.ko_with={open:"with($1) {",close:"} "})};a.$a.prototype=new a.ca;a.$a.prototype.constructor=a.$a;var b=new a.$a;0<b.Hd&&a.gc(b);a.b("jqueryTmplTemplateEngine",a.$a)})()})})();})(); 36716; 36717/// Knockout Mapping plugin v2.4.1 36718/// (c) 2013 Steven Sanderson, Roy Jacobs - http://knockoutjs.com/ 36719/// License: MIT (http://www.opensource.org/licenses/mit-license.php) 36720(function(e){"function"===typeof require&&"object"===typeof exports&&"object"===typeof module?e(require("knockout"),exports):"function"===typeof define&&define.amd?define(["knockout","exports"],e):e(ko,ko.mapping={})})(function(e,f){function y(b,c){var a,d;for(d in c)if(c.hasOwnProperty(d)&&c[d])if(a=f.getType(b[d]),d&&b[d]&&"array"!==a&&"string"!==a)y(b[d],c[d]);else if("array"===f.getType(b[d])&&"array"===f.getType(c[d])){a=b;for(var e=d,l=b[d],n=c[d],t={},g=l.length-1;0<=g;--g)t[l[g]]=l[g];for(g= 36721n.length-1;0<=g;--g)t[n[g]]=n[g];l=[];n=void 0;for(n in t)l.push(t[n]);a[e]=l}else b[d]=c[d]}function E(b,c){var a={};y(a,b);y(a,c);return a}function z(b,c){for(var a=E({},b),e=L.length-1;0<=e;e--){var f=L[e];a[f]&&(a[""]instanceof Object||(a[""]={}),a[""][f]=a[f],delete a[f])}c&&(a.ignore=h(c.ignore,a.ignore),a.include=h(c.include,a.include),a.copy=h(c.copy,a.copy),a.observe=h(c.observe,a.observe));a.ignore=h(a.ignore,j.ignore);a.include=h(a.include,j.include);a.copy=h(a.copy,j.copy);a.observe=h(a.observe, 36722j.observe);a.mappedProperties=a.mappedProperties||{};a.copiedProperties=a.copiedProperties||{};return a}function h(b,c){"array"!==f.getType(b)&&(b="undefined"===f.getType(b)?[]:[b]);"array"!==f.getType(c)&&(c="undefined"===f.getType(c)?[]:[c]);return e.utils.arrayGetDistinctValues(b.concat(c))}function F(b,c,a,d,k,l,n){var t="array"===f.getType(e.utils.unwrapObservable(c));l=l||"";if(f.isMapped(b)){var g=e.utils.unwrapObservable(b)[p];a=E(g,a)}var j=n||k,h=function(){return a[d]&&a[d].create instanceof 36723Function},x=function(b){var f=G,g=e.dependentObservable;e.dependentObservable=function(a,b,c){c=c||{};a&&"object"==typeof a&&(c=a);var d=c.deferEvaluation,M=!1;c.deferEvaluation=!0;a=new H(a,b,c);if(!d){var g=a,d=e.dependentObservable;e.dependentObservable=H;a=e.isWriteableObservable(g);e.dependentObservable=d;d=H({read:function(){M||(e.utils.arrayRemoveItem(f,g),M=!0);return g.apply(g,arguments)},write:a&&function(a){return g(a)},deferEvaluation:!0});d.__DO=g;a=d;f.push(a)}return a};e.dependentObservable.fn= 36724H.fn;e.computed=e.dependentObservable;b=e.utils.unwrapObservable(k)instanceof Array?a[d].create({data:b||c,parent:j,skip:N}):a[d].create({data:b||c,parent:j});e.dependentObservable=g;e.computed=e.dependentObservable;return b},u=function(){return a[d]&&a[d].update instanceof Function},v=function(b,f){var g={data:f||c,parent:j,target:e.utils.unwrapObservable(b)};e.isWriteableObservable(b)&&(g.observable=b);return a[d].update(g)};if(n=I.get(c))return n;d=d||"";if(t){var t=[],s=!1,m=function(a){return a}; 36725a[d]&&a[d].key&&(m=a[d].key,s=!0);e.isObservable(b)||(b=e.observableArray([]),b.mappedRemove=function(a){var c="function"==typeof a?a:function(b){return b===m(a)};return b.remove(function(a){return c(m(a))})},b.mappedRemoveAll=function(a){var c=C(a,m);return b.remove(function(a){return-1!=e.utils.arrayIndexOf(c,m(a))})},b.mappedDestroy=function(a){var c="function"==typeof a?a:function(b){return b===m(a)};return b.destroy(function(a){return c(m(a))})},b.mappedDestroyAll=function(a){var c=C(a,m);return b.destroy(function(a){return-1!= 36726e.utils.arrayIndexOf(c,m(a))})},b.mappedIndexOf=function(a){var c=C(b(),m);a=m(a);return e.utils.arrayIndexOf(c,a)},b.mappedGet=function(a){return b()[b.mappedIndexOf(a)]},b.mappedCreate=function(a){if(-1!==b.mappedIndexOf(a))throw Error("There already is an object with the key that you specified.");var c=h()?x(a):a;u()&&(a=v(c,a),e.isWriteableObservable(c)?c(a):c=a);b.push(c);return c});n=C(e.utils.unwrapObservable(b),m).sort();g=C(c,m);s&&g.sort();s=e.utils.compareArrays(n,g);n={};var J,A=e.utils.unwrapObservable(c), 36727y={},z=!0,g=0;for(J=A.length;g<J;g++){var r=m(A[g]);if(void 0===r||r instanceof Object){z=!1;break}y[r]=A[g]}var A=[],B=0,g=0;for(J=s.length;g<J;g++){var r=s[g],q,w=l+"["+g+"]";switch(r.status){case "added":var D=z?y[r.value]:K(e.utils.unwrapObservable(c),r.value,m);q=F(void 0,D,a,d,b,w,k);h()||(q=e.utils.unwrapObservable(q));w=O(e.utils.unwrapObservable(c),D,n);q===N?B++:A[w-B]=q;n[w]=!0;break;case "retained":D=z?y[r.value]:K(e.utils.unwrapObservable(c),r.value,m);q=K(b,r.value,m);F(q,D,a,d,b,w, 36728k);w=O(e.utils.unwrapObservable(c),D,n);A[w]=q;n[w]=!0;break;case "deleted":q=K(b,r.value,m)}t.push({event:r.status,item:q})}b(A);a[d]&&a[d].arrayChanged&&e.utils.arrayForEach(t,function(b){a[d].arrayChanged(b.event,b.item)})}else if(P(c)){b=e.utils.unwrapObservable(b);if(!b){if(h())return s=x(),u()&&(s=v(s)),s;if(u())return v(s);b={}}u()&&(b=v(b));I.save(c,b);
36728if(u())return b;Q(c,function(d){var f=l.length?l+"."+d:d;if(-1==e.utils.arrayIndexOf(a.ignore,f))if(-1!=e.utils.arrayIndexOf(a.copy,f))b[d]= 36729c[d];else if("object"!=typeof c[d]&&"array"!=typeof c[d]&&0<a.observe.length&&-1==e.utils.arrayIndexOf(a.observe,f))b[d]=c[d],a.copiedProperties[f]=!0;else{var g=I.get(c[d]),k=F(b[d],c[d],a,d,b,f,b),g=g||k;if(0<a.observe.length&&-1==e.utils.arrayIndexOf(a.observe,f))b[d]=g(),a.copiedProperties[f]=!0;else{if(e.isWriteableObservable(b[d])){if(g=e.utils.unwrapObservable(g),b[d]()!==g)b[d](g)}else g=void 0===b[d]?g:e.utils.unwrapObservable(g),b[d]=g;a.mappedProperties[f]=!0}}})}else switch(f.getType(c)){case "function":u()? 36730e.isWriteableObservable(c)?(c(v(c)),b=c):b=v(c):b=c;break;default:if(e.isWriteableObservable(b))return q=u()?v(b):e.utils.unwrapObservable(c),b(q),q;h()||u();b=h()?x():e.observable(e.utils.unwrapObservable(c));u()&&b(v(b))}return b}function O(b,c,a){for(var d=0,e=b.length;d<e;d++)if(!0!==a[d]&&b[d]===c)return d;return null}function R(b,c){var a;c&&(a=c(b));"undefined"===f.getType(a)&&(a=b);return e.utils.unwrapObservable(a)}function K(b,c,a){b=e.utils.unwrapObservable(b);for(var d=0,f=b.length;d< 36731f;d++){var l=b[d];if(R(l,a)===c)return l}throw Error("When calling ko.update*, the key '"+c+"' was not found!");}function C(b,c){return e.utils.arrayMap(e.utils.unwrapObservable(b),function(a){return c?R(a,c):a})}function Q(b,c){if("array"===f.getType(b))for(var a=0;a<b.length;a++)c(a);else for(a in b)c(a)}function P(b){var c=f.getType(b);return("object"===c||"array"===c)&&null!==b}function T(){var b=[],c=[];this.save=function(a,d){var f=e.utils.arrayIndexOf(b,a);0<=f?c[f]=d:(b.push(a),c.push(d))}; 36732this.get=function(a){a=e.utils.arrayIndexOf(b,a);return 0<=a?c[a]:void 0}}function S(){var b={},c=function(a){var c;try{c=a}catch(e){c="$$$"}a=b[c];void 0===a&&(a=new T,b[c]=a);return a};this.save=function(a,b){c(a).save(a,b)};this.get=function(a){return c(a).get(a)}}var p="__ko_mapping__",H=e.dependentObservable,B=0,G,I,L=["create","update","key","arrayChanged"],N={},x={include:["_destroy"],ignore:[],copy:[],observe:[]},j=x;f.isMapped=function(b){return(b=e.utils.unwrapObservable(b))&&b[p]};f.fromJS= 36733function(b){if(0==arguments.length)throw Error("When calling ko.fromJS, pass the object you want to convert.");try{B++||(G=[],I=new S);var c,a;2==arguments.length&&(arguments[1][p]?a=arguments[1]:c=arguments[1]);3==arguments.length&&(c=arguments[1],a=arguments[2]);a&&(c=E(c,a[p]));c=z(c);var d=F(a,b,c);a&&(d=a);if(!--B)for(;G.length;){var e=G.pop();e&&(e(),e.__DO.throttleEvaluation=e.throttleEvaluation)}d[p]=E(d[p],c);return d}catch(f){throw B=0,f;}};f.fromJSON=function(b){var c=e.utils.parseJson(b); 36734arguments[0]=c;return f.fromJS.apply(this,arguments)};f.updateFromJS=function(){throw Error("ko.mapping.updateFromJS, use ko.mapping.fromJS instead. Please note that the order of parameters is different!");};f.updateFromJSON=function(){throw Error("ko.mapping.updateFromJSON, use ko.mapping.fromJSON instead. Please note that the order of parameters is different!");};f.toJS=function(b,c){j||f.resetDefaultOptions();if(0==arguments.length)throw Error("When calling ko.mapping.toJS, pass the object you want to convert."); 36735if("array"!==f.getType(j.ignore))throw Error("ko.mapping.defaultOptions().ignore should be an array.");if("array"!==f.getType(j.include))throw Error("ko.mapping.defaultOptions().include should be an array.");if("array"!==f.getType(j.copy))throw Error("ko.mapping.defaultOptions().copy should be an array.");c=z(c,b[p]);return f.visitModel(b,function(a){return e.utils.unwrapObservable(a)},c)};f.toJSON=function(b,c){var a=f.toJS(b,c);return e.utils.stringifyJson(a)};f.defaultOptions=function(){if(0<arguments.length)j= 36736arguments[0];else return j};f.resetDefaultOptions=function(){j={include:x.include.slice(0),ignore:x.ignore.slice(0),copy:x.copy.slice(0)}};f.getType=function(b){if(b&&"object"===typeof b){if(b.constructor===Date)return"date";if(b.constructor===Array)return"array"}return typeof b};f.visitModel=function(b,c,a){a=a||{};a.visitedObjects=a.visitedObjects||new S;var d,k=e.utils.unwrapObservable(b);if(P(k))a=z(a,k[p]),c(b,a.parentName),d="array"===f.getType(k)?[]:{};else return c(b,a.parentName);a.visitedObjects.save(b, 36737d);var l=a.parentName;Q(k,function(b){if(!(a.ignore&&-1!=e.utils.arrayIndexOf(a.ignore,b))){var j=k[b],g=a,h=l||"";"array"===f.getType(k)?l&&(h+="["+b+"]"):(l&&(h+="."),h+=b);g.parentName=h;if(!(-1===e.utils.arrayIndexOf(a.copy,b)&&-1===e.utils.arrayIndexOf(a.include,b)&&k[p]&&k[p].mappedProperties&&!k[p].mappedProperties[b]&&k[p].copiedProperties&&!k[p].copiedProperties[b]&&"array"!==f.getType(k)))switch(f.getType(e.utils.unwrapObservable(j))){case "object":case "array":case "undefined":g=a.visitedObjects.get(j); 36738d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.parentName)}}});return d}}); 36739; 36740; 36741!function(i){"use strict";"function"==typeof define&&define.amd?define(["jquery"],i):"undefined"!=typeof exports?module.exports=i(require("jquery")):i(jQuery)}(function(i){"use strict";var e=window.Slick||{};(e=function(){var e=0;return function(t,o){var s,n=this;n.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:i(t),appendDots:i(t),arrows:!0,asNavFor:null,prevArrow:'<button class="slick-prev" aria-label="Previous" type="button">Previous</button>',nextArrow:'<button class="slick-next" aria-label="Next" type="button">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(e,t){return i('<button type="button" />').text(t+1)},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",edgeFriction:.35,fade:!1,focusOnSelect:!1,focusOnChange:!1,infinite:!0,initialSlide:0,lazyLoad:"ondemand",mobileFirst:!1,pauseOnHover:!0,pauseOnFocus:!0,pauseOnDotsHover:!1,respondTo:"window",responsive:null,rows:1,rtl:!1,slide:"",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,useTransform:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3},n.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,scrolling:!1,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,
vendor: 6,594 bytes, line 36741
36741sliding:!1,slideOffset:0,swipeLeft:null,swiping:!1,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},i.extend(n,n.initials),n.activeBreakpoint=null,n.animType=null,n.animProp=null,n.breakpoints=[],n.breakpointSettings=[],n.cssTransitions=!1,n.focussed=!1,n.interrupted=!1,n.hidden="hidden",n.paused=!0,n.positionProp=null,n.respondTo=null,n.rowCount=1,n.shouldClick=!0,n.$slider=i(t),n.$slidesCache=null,n.transformType=null,n.transitionType=null,n.visibilityChange="visibilitychange",n.windowWidth=0,n.windowTimer=null,s=i(t).data("slick")||{},n.options=i.extend({},n.defaults,o,s),n.currentSlide=n.options.initialSlide,n.originalSettings=n.options,void 0!==document.mozHidden?(n.hidden="mozHidden",n.visibilityChange="mozvisibilitychange"):void 0!==document.webkitHidden&&(n.hidden="webkitHidden",n.visibilityChange="webkitvisibilitychange"),n.autoPlay=i.proxy(n.autoPlay,n),n.autoPlayClear=i.proxy(n.autoPlayClear,n),n.autoPlayIterator=i.proxy(n.autoPlayIterator,n),n.changeSlide=i.proxy(n.changeSlide,n),n.clickHandler=i.proxy(n.clickHandler,n),n.selectHandler=i.proxy(n.selectHandler,n),n.setPosition=i.proxy(n.setPosition,n),n.swipeHandler=i.proxy(n.swipeHandler,n),n.dragHandler=i.proxy(n.dragHandler,n),n.keyHandler=i.proxy(n.keyHandler,n),n.instanceUid=e++,n.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,n.registerBreakpoints(),n.init(!0)}}()).prototype.activateADA=function(){this.$slideTrack.find(".slick-active").attr({"aria-hidden":"false"}).find("a, input, button, select").attr({tabindex:"0"})},e.prototype.addSlide=e.prototype.slickAdd=function(e,t,o){var s=this;if("boolean"==typeof t)o=t,t=null;else if(t<0||t>=s.slideCount)return!1;s.unload(),"number"==typeof t?0===t&&0===s.$slides.length?i(e).appendTo(s.$slideTrack):o?i(e).insertBefore(s.$slides.eq(t)):i(e).insertAfter(s.$slides.eq(t)):!0===o?i(e).prependTo(s.$slideTrack):i(e).appendTo(s.$slideTrack),s.$slides=s.$slideTrack.children(this.options.slide),s.$slideTrack.children(this.options.slide).detach(),s.$slideTrack.append(s.$slides),s.$slides.each(function(e,t){i(t).attr("data-slick-index",e)}),s.$slidesCache=s.$slides,s.reinit()},e.prototype.animateHeight=function(){var i=this;if(1===i.options.slidesToShow&&!0===i.options.adaptiveHeight&&!1===i.options.vertical){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.animate({height:e},i.options.speed)}},e.prototype.animateSlide=function(e,t){var o={},s=this;s.animateHeight(),!0===s.options.rtl&&!1===s.options.vertical&&(e=-e),!1===s.transformsEnabled?!1===s.options.vertical?s.$slideTrack.animate({left:e},s.options.speed,s.options.easing,t):s.$slideTrack.animate({top:e},s.options.speed,s.options.easing,t):!1===s.cssTransitions?(!0===s.options.rtl&&(s.currentLeft=-s.currentLeft),i({animStart:s.currentLeft}).animate({animStart:e},{duration:s.options.speed,easing:s.options.easing,step:function(i){i=Math.ceil(i),!1===s.options.vertical?(o[s.animType]="translate("+i+"px, 0px)",s.$slideTrack.css(o)):(o[s.animType]="translate(0px,"+i+"px)",s.$slideTrack.css(o))},complete:function(){t&&t.call()}})):(s.applyTransition(),e=Math.ceil(e),!1===s.options.vertical?o[s.animType]="translate3d("+e+"px, 0px, 0px)":o[s.animType]="translate3d(0px,"+e+"px, 0px)",s.$slideTrack.css(o),t&&setTimeout(function(){s.disableTransition(),t.call()},s.options.speed))},e.prototype.getNavTarget=function(){var e=this,t=e.options.asNavFor;return t&&null!==t&&(t=i(t).not(e.$slider)),t},e.prototype.asNavFor=function(e){var t=this.getNavTarget();null!==t&&"object"==typeof t&&t.each(function(){var t=i(this).slick("getSlick");t.unslicked||t.slideHandler(e,!0)})},e.prototype.applyTransition=function(i){var e=this,t={};!1===e.options.fade?t[e.transitionType]=e.transformType+" "+e.options.speed+"ms "+e.options.cssEase:t[e.transitionType]="opacity "+e.options.speed+"ms "+e.options.cssEase,!1===e.options.fade?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.autoPlay=function(){var i=this;i.autoPlayClear(),i.slideCount>i.options.slidesToShow&&(i.autoPlayTimer=setInterval(i.autoPlayIterator,i.options.autoplaySpeed))},e.prototype.autoPlayClear=function(){var i=this;i.autoPlayTimer&&clearInterval(i.autoPlayTimer)},e.prototype.autoPlayIterator=function(){var i=this,e=i.currentSlide+i.options.slidesToScroll;i.paused||i.interrupted||i.focussed||(!1===i.options.infinite&&(1===i.direction&&i.currentSlide+1===i.slideCount-1?i.direction=0:0===i.direction&&(e=i.currentSlide-i.options.slidesToScroll,i.currentSlide-1==0&&(i.direction=1))),i.slideHandler(e))},e.prototype.buildArrows=function(){var e=this;!0===e.options.arrows&&(e.$prevArrow=i(e.options.prevArrow).addClass("slick-arrow"),e.$nextArrow=i(e.options.nextArrow).addClass("slick-arrow"),e.slideCount>e.options.slidesToShow?(e.$prevArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),e.$nextArrow.removeClass("slick-hidden").removeAttr("aria-hidden tabindex"),e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.prependTo(e.options.appendArrows),e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.appendTo(e.options.appendArrows),!0!==e.options.infinite&&e.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true")):e.$prevArrow.add(e.$nextArrow).addClass("slick-hidden").attr({"aria-disabled":"true",tabindex:"-1"}))},e.prototype.buildDots=function(){var e,t,o=this;if(!0===o.options.dots){for(o.$slider.addClass("slick-dotted"),t=i("<ul />").addClass(o.options.dotsClass),e=0;e<=o.getDotCount();e+=1)t.append(i("<li />").append(o.options.customPaging.call(this,o,e)));o.$dots=t.appendTo(o.options.appendDots),o.$dots.find("li").first().addClass("slick-active")}},e.prototype.buildOut=function(){var e=this;e.$slides=e.$slider.children(e.options.slide+":not(.slick-cloned)").addClass("slick-slide"),e.slideCount=e.$slides.length,e.$slides.each(function(e,t){i(t).attr("data-slick-index",e).data("originalStyling",i(t).attr("style")||"")}),e.$slider.addClass("slick-slider"),e.$slideTrack=0===e.slideCount?i('<div class="slick-track"/>').appendTo(e.$slider):e.$slides.wrapAll('<div class="slick-track"/>').parent(),e.$list=e.$slideTrack.wrap('<div class="slick-list"/>').parent(),e.$slideTrack.css("opacity",0),!0!==e.options.centerMode&&!0!==e.options.swipeToSlide||(e.options.slidesToScroll=1),i("img[data-lazy]",e.$slider).not("[src]").addClass("slick-loading"),e.setupInfinite(),e.buildArrows(),e.buildDots(),e.updateDots(),e.setSlideClasses("number"==typeof e.currentSlide?e.currentSlide:0),!0===e.options.draggable&&e.$list.addClass("draggable")},e.prototype.buildRows=function(){var i,e,t,o,s,n,r,l=this;if(o=document.createDocumentFragment(),n=l.$slider.children(),l.o
vendor: 3,442 bytes, line 36741
36741ptions.rows>1){for(r=l.options.slidesPerRow*l.options.rows,s=Math.ceil(n.length/r),i=0;i<s;i++){var d=document.createElement("div");for(e=0;e<l.options.rows;e++){var a=document.createElement("div");for(t=0;t<l.options.slidesPerRow;t++){var c=i*r+(e*l.options.slidesPerRow+t);n.get(c)&&a.appendChild(n.get(c))}d.appendChild(a)}o.appendChild(d)}l.$slider.empty().append(o),l.$slider.children().children().children().css({width:100/l.options.slidesPerRow+"%",display:"inline-block"})}},e.prototype.checkResponsive=function(e,t){var o,s,n,r=this,l=!1,d=r.$slider.width(),a=window.innerWidth||i(window).width();if("window"===r.respondTo?n=a:"slider"===r.respondTo?n=d:"min"===r.respondTo&&(n=Math.min(a,d)),r.options.responsive&&r.options.responsive.length&&null!==r.options.responsive){s=null;for(o in r.breakpoints)r.breakpoints.hasOwnProperty(o)&&(!1===r.originalSettings.mobileFirst?n<r.breakpoints[o]&&(s=r.breakpoints[o]):n>r.breakpoints[o]&&(s=r.breakpoints[o]));null!==s?null!==r.activeBreakpoint?(s!==r.activeBreakpoint||t)&&(r.activeBreakpoint=s,"unslick"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),!0===e&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):(r.activeBreakpoint=s,"unslick"===r.breakpointSettings[s]?r.unslick(s):(r.options=i.extend({},r.originalSettings,r.breakpointSettings[s]),!0===e&&(r.currentSlide=r.options.initialSlide),r.refresh(e)),l=s):null!==r.activeBreakpoint&&(r.activeBreakpoint=null,r.options=r.originalSettings,!0===e&&(r.currentSlide=r.options.initialSlide),r.refresh(e),l=s),e||!1===l||r.$slider.trigger("breakpoint",[r,l])}},e.prototype.changeSlide=function(e,t){var o,s,n,r=this,l=i(e.currentTarget);switch(l.is("a")&&e.preventDefault(),l.is("li")||(l=l.closest("li")),n=r.slideCount%r.options.slidesToScroll!=0,o=n?0:(r.slideCount-r.currentSlide)%r.options.slidesToScroll,e.data.message){case"previous":s=0===o?r.options.slidesToScroll:r.options.slidesToShow-o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide-s,!1,t);break;case"next":s=0===o?r.options.slidesToScroll:o,r.slideCount>r.options.slidesToShow&&r.slideHandler(r.currentSlide+s,!1,t);break;case"index":var d=0===e.data.index?0:e.data.index||l.index()*r.options.slidesToScroll;r.slideHandler(r.checkNavigable(d),!1,t),l.children().trigger("focus");break;default:return}},e.prototype.checkNavigable=function(i){var e,t;if(e=this.getNavigableIndexes(),t=0,i>e[e.length-1])i=e[e.length-1];else for(var o in e){if(i<e[o]){i=t;break}t=e[o]}return i},e.prototype.cleanUpEvents=function(){var e=this;e.options.dots&&null!==e.$dots&&(i("li",e.$dots).off("click.slick",e.changeSlide).off("mouseenter.slick",i.proxy(e.interrupt,e,!0)).off("mouseleave.slick",i.proxy(e.interrupt,e,!1)),!0===e.options.accessibility&&e.$dots.off("keydown.slick",e.keyHandler)),e.$slider.off("focus.slick blur.slick"),!0===e.options.arrows&&e.slideCount>e.options.slidesToShow&&(e.$prevArrow&&e.$prevArrow.off("click.slick",e.changeSlide),e.$nextArrow&&e.$nextArrow.off("click.slick",e.changeSlide),!0===e.options.accessibility&&(e.$prevArrow&&e.$prevArrow.off("keydown.slick",e.keyHandler),e.$nextArrow&&e.$nextArrow.off("keydown.slick",e.keyHandler))),e.$list.off("touchstart.slick mousedown.slick",e.swipeHandler),e.$list.off("touchmove.slick mousemove.slick",e.swipeHandler),e.$list.off("touchend.slick mouseup.slick",e.swipeHandler),e.$list.off("touchcancel.slick mouseleave.
36741slick",e.swipeHandler),e.$list.off("click.slick",e.clickHandler),i(document).off(e.visibilityChange,e.visibility),e.cleanUpSlideEvents(),!0===e.options.accessibility&&e.$list.off("keydown.slick",e.keyHandler),!0===e.options.focusOnSelect&&i(e.$slideTrack).children().off("click.slick",e.selectHandler),i(window).off("orientationchange.slick.slick-"+e.instanceUid,e.orientationChange),i(window).off("resize.slick.slick-"+e.instanceUid,e.resize),i("[draggable!=true]",e.$slideTrack).off("dragstart",e.preventDefault),i(window).off("load.slick.slick-"+e.instanceUid,e.setPosition)},e.prototype.cleanUpSlideEvents=function(){var e=this;e.$list.off("mouseenter.slick",i.proxy(e.interrupt,e,!0)),e.$list.off("mouseleave.slick",i.proxy(e.interrupt,e,!1))},e.prototype.cleanUpRows=function(){var i,e=this;e.options.rows>1&&((i=e.$slides.children().children()).removeAttr("style"),e.$slider.empty().append(i))},e.prototype.clickHandler=function(i){!1===this.shouldClick&&(i.stopImmediatePropagation(),i.stopPropagation(),i.preventDefault())},e.prototype.destroy=function(e){var t=this;t.autoPlayClear(),t.touchObject={},t.cleanUpEvents(),i(".slick-cloned",t.$slider).detach(),t.$dots&&t.$dots.remove(),t.$prevArrow&&t.$prevArrow.length&&(t.$prevArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),t.htmlExpr.test(t.options.prevArrow)&&t.$prevArrow.remove()),t.$nextArrow&&t.$nextArrow.length&&(t.$nextArrow.removeClass("slick-disabled slick-arrow slick-hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),t.htmlExpr.test(t.options.nextArrow)&&t.$nextArrow.remove()),t.$slides&&(t.$slides.removeClass("slick-slide slick-active slick-center slick-visible slick-current").removeAttr("aria-hidden").removeAttr("data-slick-index").each(function(){i(this).attr("style",i(this).data("originalStyling"))}),t.$slideTrack.children(this.options.slide).detach(),t.$slideTrack.detach(),t.$list.detach(),t.$slider.append(t.$slides)),t.cleanUpRows(),t.$slider.removeClass("slick-slider"),t.$slider.removeClass("slick-initialized"),t.$slider.removeClass("slick-dotted"),t.unslicked=!0,e||t.$slider.trigger("destroy",[t])},e.prototype.disableTransition=function(i){var e=this,t={};t[e.transitionType]="",!1===e.options.fade?e.$slideTrack.css(t):e.$slides.eq(i).css(t)},e.prototype.fadeSlide=function(i,e){var t=this;!1===t.cssTransitions?(t.$slides.eq(i).css({zIndex:t.options.zIndex}),t.$slides.eq(i).animate({opacity:1},t.options.speed,t.options.easing,e)):(t.applyTransition(i),t.$slides.eq(i).css({opacity:1,zIndex:t.options.zIndex}),e&&setTimeout(function(){t.disableTransition(i),e.call()},t.options.speed))},e.prototype.fadeSlideOut=function(i){var e=this;!1===e.cssTransitions?e.$slides.eq(i).animate({opacity:0,zIndex:e.options.zIndex-2},e.options.speed,e.options.easing):(e.applyTransition(i),e.$slides.eq(i).css({opacity:0,zIndex:e.options.zIndex-2}))},e.prototype.filterSlides=e.prototype.slickFilter=function(i){var e=this;null!==i&&(e.$slidesCache=e.$slides,e.unload(),e.$slideTrack.children(this.options.slide).detach(),e.$slidesCache.filter(i).appendTo(e.$slideTrack),e.reinit())},e.prototype.focusHandler=function(){var e=this;e.$slider.off("focus.slick blur.slick").on("focus.slick blur.slick","*",function(t){t.stopImmediatePropagation();var o=i(this);setTimeout(function(){e.options.pauseOnFocus&&(e.focussed=o.is(":focus"),e.autoPlay())},0)})},e.prototype.getCurrent=e.prototype.slickCurrentSlide=function(){return this.currentSlide},e.prototype.getDotCount=function(){var i=this,e=0,t=0,o=0;if(!0===i.options.infinite)if(i.slideCount<=i.options.slidesToShow)++o;else for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else if(!0===i.options.centerMode)o=i.slideCount;else if(i.options.asNavFor)for(;e<i.slideCount;)++o,e=t+i.options.slidesToScroll,t+=i.options.slidesToScroll<=i.options.slidesToShow?i.options.slidesToScroll:i.options.slidesToShow;else o=1+Math.ceil((i.slideCount-i.options.slidesToShow)/i.options.slidesToScroll);return o-1},e.prototype.getLeft=function(i){var e,t,o,s,n=this,r=0;return n.slideOffset=0,t=n.$slides.first().outerHeight(!0),!0===n.options.infinite?(n.slideCount>n.options.slidesToShow&&(n.slideOffset=n.slideWidth*n.options.slidesToShow*-1,s=-1,!0===n.options.vertical&&!0===n.options.centerMode&&(2===n.options.slidesToShow?s=-1.5:1===n.options.slidesToShow&&(s=-2)),r=t*n.options.slidesToShow*s),n.slideCount%n.options.slidesToScroll!=0&&i+n.options.slidesToScroll>n.slideCount&&n.slideCount>n.options.slidesToShow&&(i>n.slideCount?(n.slideOffset=(n.options.slidesToShow-(i-n.slideCount))*n.slideWidth*-1,r=(n.options.slidesToShow-(i-n.slideCount))*t*-1):(n.slideOffset=n.slideCount%n.options.slidesToScroll*n.slideWidth*-1,r=n.slideCount%n.options.slidesToScroll*t*-1))):i+n.options.slidesToShow>n.slideCount&&(n.slideOffset=(i+n.options.slidesToShow-n.slideCount)*n.slideWidth,r=(i+n.options.slidesToShow-n.slideCount)*t),n.slideCount<=n.options.slidesToShow&&(n.slideOffset=0,r=0),!0===n.options.centerMode&&n.slideCount<=n.options.slidesToShow?n.slideOffset=n.slideWidth*Math.floor(n.options.slidesToShow)/2-n.slideWidth*n.slideCount/2:!0===n.options.centerMode&&!0===n.options.infinite?n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)-n.slideWidth:!0===n.options.centerMode&&(n.slideOffset=0,n.slideOffset+=n.slideWidth*Math.floor(n.options.slidesToShow/2)),e=!1===n.options.vertical?i*n.slideWidth*-1+n.slideOffset:i*t*-1+r,!0===n.options.variableWidth&&(o=n.slideCount<=n.options.slidesToShow||!1===n.options.infinite?n.$slideTrack.children(".slick-slide").eq(i):n.$slideTrack.children(".slick-slide").eq(i+n.options.slidesToShow),e=!0===n.options.rtl?o[0]?-1*(n.$slideTrack.width()-o[0].offsetLeft-o.width()):0:o[0]?-1*o[0].offsetLeft:0,!0===n.options.centerMode&&(o=n.slideCount<=n.options.slidesToShow||!1===n.options.infinite?n.$slideTrack.children(".slick-slide").eq(i):n.$slideTrack.children(".slick-slide").eq(i+n.options.slidesToShow+1),e=!0===n.options.rtl?o[0]?-1*(n.$slideTrack.width()-o[0].offsetLeft-o.width()):0:o[0]?-1*o[0].offsetLeft:0,e+=(n.$list.width()-o.outerWidth())/2)),e},e.prototype.getOption=e.prototype.slickGetOption=function(i){return this.options[i]},e.prototype.getNavigableIndexes=function(){var i,e=this,t=0,o=0,s=[];for(!1===e.options.infinite?i=e.slideCount:(t=-1*e.options.slidesToScroll,o=-1*e.options.slidesToScroll,i=2*e.slideCount);t<i;)s.push(t),t=o+e.options.slidesToScroll,o+=e.options.slidesToScroll<=e.options.slidesToShow?e.options.slidesToScroll:e.options.slidesToShow;return s},e.prototype.getSlick=function(){return this},e.prototype.getSlideCount=function(){var e,t,o=this;return t=!0===o.options.centerMode?o.slideWidth*Math.floor(o.options.slidesToShow/2):0,!0===o.options.swipeToSlide?(o.$slideTrack.find(".slick-slide").each(function(s,n){if(n.offsetLeft-t+i(n).outerWidth()/2>-1*o.swipeLeft)return e=n,!1}),Math.abs(i(e).attr("data-slick-index")-o.currentSlide)||1):o.options.slidesToScroll},e.prototype.goTo=e.prototype.slickGoTo=function(i,e){this.changeSlide({data:{message:"index",index:
36741parseInt(i)}},e)},e.prototype.init=function(e){var t=this;i(t.$slider).hasClass("slick-initialized")||(i(t.$slider).addClass("slick-initialized"),t.buildRows(),t.buildOut(),t.setProps(),t.startLoad(),t.loadSlider(),t.initializeEvents(),t.updateArrows(),t.updateDots(),t.checkResponsive(!0),t.focusHandler()),e&&t.$slider.trigger("init",[t]),!0===t.options.accessibility&&t.initADA(),t.options.autoplay&&(t.paused=!1,t.autoPlay())},e.prototype.initADA=function(){var e=this,t=Math.ceil(e.slideCount/e.options.slidesToShow),o=e.getNavigableIndexes().filter(function(i){return i>=0&&i<e.slideCount});e.$slides.add(e.$slideTrack.find(".slick-cloned")).attr({"aria-hidden":"true",tabindex:"-1"}).find("a, input, button, select").attr({tabindex:"-1"}),null!==e.$dots&&(e.$slides.not(e.$slideTrack.find(".slick-cloned")).each(function(t){var s=o.indexOf(t);i(this).attr({role:"tabpanel",id:"slick-slide"+e.instanceUid+t,tabindex:-1}),-1!==s&&i(this).attr({"aria-describedby":"slick-slide-control"+e.instanceUid+s})}),e.$dots.attr("role","tablist").find("li").each(function(s){var n=o[s];i(this).attr({role:"presentation"}),i(this).find("button").first().attr({role:"tab",id:"slick-slide-control"+e.instanceUid+s,"aria-controls":"slick-slide"+e.instanceUid+n,"aria-label":s+1+" of "+t,"aria-selected":null,tabindex:"-1"})}).eq(e.currentSlide).find("button").attr({"aria-selected":"true",tabindex:"0"}).end());for(var s=e.currentSlide,n=s+e.options.slidesToShow;s<n;s++)e.$slides.eq(s).attr("tabindex",0);e.activateADA()},e.prototype.initArrowEvents=function(){var i=this;!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.off("click.slick").on("click.slick",{message:"previous"},i.changeSlide),i.$nextArrow.off("click.slick").on("click.slick",{message:"next"},i.changeSlide),!0===i.options.accessibility&&(i.$prevArrow.on("keydown.slick",i.keyHandler),i.$nextArrow.on("keydown.slick",i.keyHandler)))},e.prototype.initDotEvents=function(){var e=this;!0===e.options.dots&&(i("li",e.$dots).on("click.slick",{message:"index"},e.changeSlide),!0===e.options.accessibility&&e.$dots.on("keydown.slick",e.keyHandler)),!0===e.options.dots&&!0===e.options.pauseOnDotsHover&&i("li",e.$dots).on("mouseenter.slick",i.proxy(e.interrupt,e,!0)).on("mouseleave.slick",i.proxy(e.interrupt,e,!1))},e.prototype.initSlideEvents=function(){var e=this;e.options.pauseOnHover&&(e.$list.on("mouseenter.slick",i.proxy(e.interrupt,e,!0)),e.$list.on("mouseleave.slick",i.proxy(e.interrupt,e,!1)))},e.prototype.initializeEvents=function(){var e=this;e.initArrowEvents(),e.initDotEvents(),e.initSlideEvents(),e.$list.on("touchstart.slick mousedown.slick",{action:"start"},e.swipeHandler),e.$list.on("touchmove.slick mousemove.slick",{action:"move"},e.swipeHandler),e.$list.on("touchend.slick mouseup.slick",{action:"end"}
36741,e.swipeHandler),e.$list.on("touchcancel.slick mouseleave.slick",{action:"end"},e.swipeHandler),e.$list.on("click.slick",e.clickHandler),i(document).on(e.visibilityChange,i.proxy(e.visibility,e)),!0===e.options.accessibility&&e.$list.on("keydown.slick",e.keyHandler),!0===e.options.focusOnSelect&&i(e.$slideTrack).children().on("click.slick",e.selectHandler),i(window).on("orientationchange.slick.slick-"+e.instanceUid,i.proxy(e.orientationChange,e)),i(window).on("resize.slick.slick-"+e.instanceUid,i.proxy(e.resize,e)),i("[draggable!=true]",e.$slideTrack).on("dragstart",e.preventDefault),i(window).on("load.slick.slick-"+e.instanceUid,e.setPosition),i(e.setPosition)},e.prototype.initUI=function(){var i=this;!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.show(),i.$nextArrow.show()),!0===i.options.dots&&i.slideCount>i.options.slidesToShow&&i.$dots.show()},e.prototype.keyHandler=function(i){var e=this;i.target.tagName.match("TEXTAREA|INPUT|SELECT")||(37===i.keyCode&&!0===e.options.accessibility?e.changeSlide({data:{message:!0===e.options.rtl?"next":"previous"}}):39===i.keyCode&&!0===e.options.accessibility&&e.changeSlide({data:{message:!0===e.options.rtl?"previous":"next"}}))},e.prototype.lazyLoad=function(){function e(e){i("img[data-lazy]",e).each(function(){var e=i(this),t=i(this).attr("data-lazy"),o=i(this).attr("data-srcset"),s=i(this).attr("data-sizes")||n.$slider.attr("data-sizes"),r=document.createElement("img");r.onload=function(){e.animate({opacity:0}
vendor: 5,619 bytes, line 36741
36741,100,function(){o&&(e.attr("srcset",o),s&&e.attr("sizes",s)),e.attr("src",t).animate({opacity:1},200,function(){e.removeAttr("data-lazy data-srcset data-sizes").removeClass("slick-loading")}),n.$slider.trigger("lazyLoaded",[n,e,t])})},r.onerror=function(){e.removeAttr("data-lazy").removeClass("slick-loading").addClass("slick-lazyload-error"),n.$slider.trigger("lazyLoadError",[n,e,t])},r.src=t})}var t,o,s,n=this;if(!0===n.options.centerMode?!0===n.options.infinite?s=(o=n.currentSlide+(n.options.slidesToShow/2+1))+n.options.slidesToShow+2:(o=Math.max(0,n.currentSlide-(n.options.slidesToShow/2+1)),s=n.options.slidesToShow/2+1+2+n.currentSlide):(o=n.options.infinite?n.options.slidesToShow+n.currentSlide:n.currentSlide,s=Math.ceil(o+n.options.slidesToShow),!0===n.options.fade&&(o>0&&o--,s<=n.slideCount&&s++)),t=n.$slider.find(".slick-slide").slice(o,s),"anticipated"===n.options.lazyLoad)for(var r=o-1,l=s,d=n.$slider.find(".slick-slide"),a=0;a<n.options.slidesToScroll;a++)r<0&&(r=n.slideCount-1),t=(t=t.add(d.eq(r))).add(d.eq(l)),r--,l++;e(t),n.slideCount<=n.options.slidesToShow?e(n.$slider.find(".slick-slide")):n.currentSlide>=n.slideCount-n.options.slidesToShow?e(n.$slider.find(".slick-cloned").slice(0,n.options.slidesToShow)):0===n.currentSlide&&e(n.$slider.find(".slick-cloned").slice(-1*n.options.slidesToShow))},e.prototype.loadSlider=function(){var i=this;i.setPosition(),i.$slideTrack.css({opacity:1}),i.$slider.removeClass("slick-loading"),i.initUI(),"progressive"===i.options.lazyLoad&&i.progressiveLazyLoad()},e.prototype.next=e.prototype.slickNext=function(){this.changeSlide({data:{message:"next"}})},e.prototype.orientationChange=function(){var i=this;i.checkResponsive(),i.setPosition()},e.prototype.pause=e.prototype.slickPause=function(){var i=this;i.autoPlayClear(),i.paused=!0},e.prototype.play=e.prototype.slickPlay=function(){var i=this;i.autoPlay(),i.options.autoplay=!0,i.paused=!1,i.focussed=!1,i.interrupted=!1},e.prototype.postSlide=function(e){var t=this;t.unslicked||(t.$slider.trigger("afterChange",[t,e]),t.animating=!1,t.slideCount>t.options.slidesToShow&&t.setPosition(),t.swipeLeft=null,t.options.autoplay&&t.autoPlay(),!0===t.options.accessibility&&(t.initADA(),t.options.focusOnChange&&i(t.$slides.get(t.currentSlide)).attr("tabindex",0).focus()))},e.prototype.prev=e.prototype.slickPrev=function(){this.changeSlide({data:{message:"previous"}})},e.prototype.preventDefault=function(i){i.preventDefault()},e.prototype.progressiveLazyLoad=function(e){e=e||1;var t,o,s,n,r,l=this,d=i("img[data-lazy]",l.$slider);d.length?(t=d.first(),o=t.attr("data-lazy"),s=t.attr("data-srcset"),n=t.attr("data-sizes")||l.$slider.attr("data-sizes"),(r=document.createElement("img")).onload=function(){s&&(t.attr("srcset",s),n&&t.attr("sizes",n)),t.attr("src",o).removeAttr("data-lazy data-srcset data-sizes").removeClass("slick-loading"),!0===l.options.adaptiveHeight&&l.setPosition(),l.$slider.trigger("lazyLoaded",[l,t,o]),l.progressiveLazyLoad()},r.onerror=function(){e<3?setTimeout(function(){l.progressiveLazyLoad(e+1)},500):(t.removeAttr("data-lazy").removeClass("slick-loading").addClass("slick-lazyload-error"),l.$slider.trigger("lazyLoadError",[l,t,o]),l.progressiveLazyLoad())},r.src=o):l.$slider.trigger("allImagesLoaded",[l])},e.prototype.refresh=function(e){var t,o,s=this;o=s.slideCount-s.options.slidesToShow,!s.options.infinite&&s.currentSlide>o&&(s.currentSlide=o),s.slideCount<=s.options.slidesToShow&&(s.currentSlide=0),t=s.currentSlide,s.destroy(!0),i.extend(s,s.initials,{currentSlide:t}),s.init(),e||s.changeSlide({data:{message:"index",index:t}},!1)},e.prototype.registerBreakpoints=function(){var e,t,o,s=this,n=s.options.responsive||null;if("array"===i.type(n)&&n.length){s.respondTo=s.options.respondTo||"window";for(e in n)if(o=s.breakpoints.length-1,n.hasOwnProperty(e)){for(t=n[e].breakpoint;o>=0;)s.breakpoints[o]&&s.breakpoints[o]===t&&s.breakpoints.splice(o,1),o--;s.breakpoints.push(t),s.breakpointSettings[t]=n[e].settings}s.breakpoints.sort(function(i,e){return s.options.mobileFirst?i-e:e-i})}},e.prototype.reinit=function(){var e=this;e.$slides=e.$slideTrack.children(e.options.slide).addClass("slick-slide"),e.slideCount=e.$slides.length,e.currentSlide>=e.slideCount&&0!==e.currentSlide&&(e.currentSlide=e.currentSlide-e.options.slidesToScroll),e.slideCount<=e.options.slidesToShow&&(e.currentSlide=0),e.registerBreakpoints(),e.setProps(),e.setupInfinite(),e.buildArrows(),e.updateArrows(),e.initArrowEvents(),e.buildDots(),e.updateDots(),e.initDotEvents(),e.cleanUpSlideEvents(),e.initSlideEvents(),e.checkResponsive(!1,!0),!0===e.options.focusOnSelect&&i(e.$slideTrack).children().on("click.slick",e.selectHandler),e.setSlideClasses("number"==typeof e.currentSlide?e.currentSlide:0),e.setPosition(),e.focusHandler(),e.paused=!e.options.autoplay,e.autoPlay(),e.$slider.trigger("reInit",[e])},e.prototype.resize=function(){var e=this;i(window).width()!==e.windowWidth&&(clearTimeout(e.windowDelay),e.windowDelay=window.setTimeout(function(){e.windowWidth=i(window).width(),e.checkResponsive(),e.unslicked||e.setPosition()},50))},e.prototype.removeSlide=e.prototype.slickRemove=function(i,e,t){var o=this;if(i="boolean"==typeof i?!0===(e=i)?0:o.slideCount-1:!0===e?--i:i,o.slideCount<1||i<0||i>o.slideCount-1)return!1;o.unload(),!0===t?o.$slideTrack.children().remove():o.$slideTrack.children(this.options.slide).eq(i).remove(),o.$slides=o.$slideTrack.children(this.options.slide),o.$slideTrack.children(this.options.slide).detach(),o.$slideTrack.append(o.$slides),o.$slidesCache=o.$slides,o.reinit()},e.prototype.setCSS=function(i){var e,t,o=this,s={};
36741!0===o.options.rtl&&(i=-i),e="left"==o.positionProp?Math.ceil(i)+"px":"0px",t="top"==o.positionProp?Math.ceil(i)+"px":"0px",s[o.positionProp]=i,!1===o.transformsEnabled?o.$slideTrack.css(s):(s={},!1===o.cssTransitions?(s[o.animType]="translate("+e+", "+t+")",o.$slideTrack.css(s)):(s[o.animType]="translate3d("+e+", "+t+", 0px)",o.$slideTrack.css(s)))},e.prototype.setDimensions=function(){var i=this;!1===i.options.vertical?!0===i.options.centerMode&&i.$list.css({padding:"0px "+i.options.centerPadding}):(i.$list.height(i.$slides.first().outerHeight(!0)*i.options.slidesToShow),!0===i.options.centerMode&&i.$list.css({padding:i.options.centerPadding+" 0px"})),i.listWidth=i.$list.width(),i.listHeight=i.$list.height(),!1===i.options.vertical&&!1===i.options.variableWidth?(i.slideWidth=Math.ceil(i.listWidth/i.options.slidesToShow),i.$slideTrack.width(Math.ceil(i.slideWidth*i.$slideTrack.children(".slick-slide").length))):!0===i.options.variableWidth?i.$slideTrack.width(5e3*i.slideCount):(i.slideWidth=Math.ceil(i.listWidth),i.$slideTrack.height(Math.ceil(i.$slides.first().outerHeight(!0)*i.$slideTrack.children(".slick-slide").length)));var e=i.$slides.first().outerWidth(!0)-i.$slides.first().width();!1===i.options.variableWidth&&i.$slideTrack.children(".slick-slide").width(i.slideWidth-e)},e.prototype.setFade=function(){var e,t=this;t.$slides.each(function(o,s){e=t.slideWidth*o*-1,!0===t.options.rtl?i(s).css({position:"relative",right:e,top:0,zIndex:t.options.zIndex-2,opacity:0}
36741):i(s).css({position:"relative",left:e,top:0,zIndex:t.options.zIndex-2,opacity:0})}),t.$slides.eq(t.currentSlide).css({zIndex:t.options.zIndex-1,opacity:1})},e.prototype.setHeight=function(){var i=this;if(1===i.options.slidesToShow&&!0===i.options.adaptiveHeight&&!1===i.options.vertical){var e=i.$slides.eq(i.currentSlide).outerHeight(!0);i.$list.css("height",e)}},e.prototype.setOption=e.prototype.slickSetOption=function(){var e,t,o,s,n,r=this,l=!1;if("object"===i.type(arguments[0])?(o=arguments[0],l=arguments[1],n="multiple"):"string"===i.type(arguments[0])&&(o=arguments[0],s=arguments[1],l=arguments[2],"responsive"===arguments[0]&&"array"===i.type(arguments[1])?n="responsive":void 0!==arguments[1]&&(n="single")),"single"===n)r.options[o]=s;else if("multiple"===n)i.each(o,function(i,e){r.options[i]=e});else if("responsive"===n)for(t in s)if("array"!==i.type(r.options.responsive))r.options.responsive=[s[t]];else{for(e=r.options.responsive.length-1;e>=0;)r.options.responsive[e].breakpoint===s[t].breakpoint&&r.options.responsive.splice(e,1),e--;r.options.responsive.push(s[t])}l&&(r.unload(),r.reinit())},e.prototype.setPosition=function(){var i=this;i.setDimensions(),i.setHeight(),!1===i.options.fade?i.setCSS(i.getLeft(i.currentSlide)):i.setFade(),i.$slider.trigger("setPosition",[i])},e.prototype.setProps=function(){var i=this,e=document.body.style;i.positionProp=!0===i.options.vertical?"top":"left","top"===i.positionProp?i.$slider.addClass("slick-vertical"):i.$slider.removeClass("slick-vertical"),void 0===e.WebkitTransition&&void 0===e.MozTransition&&void 0===e.msTransition||!0===i.options.useCSS&&(i.cssTransitions=!0),i.options.fade&&("number"==typeof i.options.zIndex?i.options.zIndex<3&&(i.options.zIndex=3):i.options.zIndex=i.defaults.zIndex),void 0!==e.OTransform&&(i.animType="OTransform",i.transformType="-o-transform",i.transitionType="OTransition",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.MozTransform&&(i.animType="MozTransform",i.transformType="-moz-transform",i.transitionType="MozTransition",void 0===e.perspectiveProperty&&void 0===e.MozPerspective&&(i.animType=!1)),void 0!==e.webkitTransform&&(i.animType="webkitTransform",i.transformType="-webkit-transform",i.transitionType="webkitTransition",void 0===e.perspectiveProperty&&void 0===e.webkitPerspective&&(i.animType=!1)),void 0!==e.msTransform&&(i.animType="msTransform",i.transformType="-ms-transform",i.transitionType="msTransition",void 0===e.msTransform&&(i.animType=!1)),void 0!==e.transform&&!1!==i.animType&&(i.animType="transform",i.transformType="transform",i.transitionType="transition"),i.transformsEnabled=i.options.useTransform&&null!==i.animType&&!1!==i.animType},e.prototype.setSlideClasses=function(i){var e,t,o,s,n=this;if(t=n.$slider.find(".slick-slide").removeClass("slick-active slick-center slick-current").attr("aria-hidden","true"),n.$slides.eq(i).addClass("slick-current"),!0===n.options.centerMode){var r=n.options.slidesToShow%2==0?1:0;e=Math.floor(n.options.slidesToShow/2),!0===n.options.infinite&&(i>=e&&i<=n.slideCount-1-e?n.$slides.slice(i-e+r,i+e+1).addClass("slick-active").attr("aria-hidden","false"):(o=n.options.slidesToShow+i,t.slice(o-e+1+r,o+e+2).addClass("slick-active").attr("aria-hidden","false")),0===i?t.eq(t.length-1-n.options.slidesToShow).addClass("slick-center"):i===n.slideCount-1&&t.eq(n.options.slidesToShow).addClass("slick-center")),n.$slides.eq(i).addClass("slick-center")}else i>=0&&i<=n.slideCount-n.options.slidesToShow?n.$slides.slice(i,i+n.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false"):t.length<=n.options.slidesToShow?t.addClass("slick-active").attr("aria-hidden","false"):(s=n.slideCount%n.options.slidesToShow,o=!0===n.options.infinite?n.options.slidesToShow+i:i,n.options.slidesToShow==n.options.slidesToScroll&&n.slideCount-i<n.options.slidesToShow?t.slice(o-(n.options.slidesToShow-s),o+s).addClass("slick-active").attr("aria-hidden","false"):t.slice(o,o+n.options.slidesToShow).addClass("slick-active").attr("aria-hidden","false"));"ondemand"!==n.options.lazyLoad&&"anticipated"!==n.options.lazyLoad||n.lazyLoad()},e.prototype.setupInfinite=function(){var e,t,o,s=this;if(!0===s.options.fade&&(s.options.centerMode=!1),!0===s.options.infinite&&!1===s.options.fade&&(t=null,s.slideCount>s.options.slidesToShow)){for(o=!0===s.options.centerMode?s.options.slidesToShow+1:s.options.slidesToShow,e=s.slideCount;e>s.slideCount-o;e-=1)t=e-1,i(s.$slides[t]).clone(!0).attr("id","").attr("data-slick-index",t-s.slideCount).prependTo(s.$slideTrack).addClass("slick-cloned");for(e=0;e<o+s.slideCount;e+=1)t=e,i(s.$slides[t]).clone(!0).attr("id","").attr("data-slick-index",t+s.slideCount).appendTo(s.$slideTrack).addClass("slick-cloned");s.$slideTrack.find(".slick-cloned").find("[id]").each(function(){i(this).attr("id","")})}},e.prototype.interrupt=function(i){var e=this;i||e.autoPlay(),e.interrupted=i},e.prototype.selectHandler=function(e){var t=this,o=i(e.target).is(".slick-slide")?i(e.target):i(e.target).parents(".slick-slide"),s=parseInt(o.attr("data-slick-index"));s||(s=0),t.slideCount<=t.options.slidesToShow?t.slideHandler(s,!1,!0):t.slideHandler(s)},e.prototype.slideHandler=function(i,e,t){var o,s,n,r,l,d=null,a=this;if(e=e||!1,!(!0===a.animating&&!0===a.options.waitForAnimate||!0===a.options.fade&&a.currentSlide===i))if(!1===e&&a.asNavFor(i),o=i,d=a.getLeft(o),r=a.getLeft(a.currentSlide),a.currentLeft=null===a.swipeLeft?r:a.swipeLeft,!1===a.options.infinite&&!1===a.options.centerMode&&(i<0||i>a.getDotCount()*a.options.slidesToScroll))!1===a.options.fade&&(o=a.currentSlide,!0!==t?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o));else if(!1===a.options.infinite&&!0===a.options.centerMode&&(i<0||i>a.slideCount-a.options.slidesToScroll))!1===a.options.fade&&(o=a.currentSlide,!0!==t?a.animateSlide(r,function(){a.postSlide(o)}):a.postSlide(o));else{if(a.options.autoplay&&clearInterval(a.autoPlayTimer),s=o<0?a.slideCount%a.options.slidesToScroll!=0?a.slideCount-a.slideCount%a.options.slidesToScroll:a.slideCount+
36741o:o>=a.slideCount?a.slideCount%a.options.slidesToScroll!=0?0:o-a.slideCount:o,a.animating=!0,a.$slider.trigger("beforeChange",[a,a.currentSlide,s]),n=a.currentSlide,a.currentSlide=s,a.setSlideClasses(a.currentSlide),a.options.asNavFor&&(l=(l=a.getNavTarget()).slick("getSlick")).slideCount<=l.options.slidesToShow&&l.setSlideClasses(a.currentSlide),a.updateDots(),a.updateArrows(),!0===a.options.fade)return!0!==t?(a.fadeSlideOut(n),a.fadeSlide(s,function(){a.postSlide(s)})):a.postSlide(s),void a.animateHeight();!0!==t?a.animateSlide(d,function(){a.postSlide(s)}):a.postSlide(s)}},e.prototype.startLoad=function(){var i=this;!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&(i.$prevArrow.hide(),i.$nextArrow.hide()),!0===i.options.dots&&i.slideCount>i.options.slidesToShow&&i.$dots.hide(),i.$slider.addClass("slick-loading")},e.prototype.swipeDirection=function(){var i,e,t,o,s=this;return i=s.touchObject.startX-s.touchObject.curX,e=s.touchObject.startY-s.touchObject.curY,t=Math.atan2(e,i),(o=Math.round(180*t/Math.PI))<0&&(o=360-Math.abs(o)),o<=45&&o>=0?!1===s.options.rtl?"left":"right":o<=360&&o>=315?!1===s.options.rtl?"left":"right":o>=135&&o<=225?!1===s.options.rtl?"right":"left":!0===s.options.verticalSwiping?o>=35&&o<=135?"down":"up":"vertical"},e.prototype.swipeEnd=function(i){var e,t,o=this;if(o.dragging=!1,o.swiping=!1,o.scrolling)return o.scrolling=!1,!1;if(o.interrupted=!1,o.shouldClick=!(o.touchObject.swipeLength>10),void 0===o.touchObject.curX)return!1;if(!0===o.touchObject.edgeHit&&o.$slider.trigger("edge",[o,o.swipeDirection()]),o.touchObject.swipeLength>=o.touchObject.minSwipe){switch(t=o.swipeDirection()){case"left":case"down":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide+o.getSlideCount()):o.currentSlide+o.getSlideCount(),o.currentDirection=0;break;case"right":case"up":e=o.options.swipeToSlide?o.checkNavigable(o.currentSlide-o.getSlideCount()):o.currentSlide-o.getSlideCount(),o.currentDirection=1}"vertical"!=t&&(o.slideHandler(e),o.touchObject={},o.$slider.trigger("swipe",[o,t]))}else o.touchObject.startX!==o.touchObject.curX&&(o.slideHandler(o.currentSlide),o.touchObject={})},e.prototype.swipeHandler=function(i){var e=this;if(!(!1===e.options.swipe||"ontouchend"in document&&!1===e.options.swipe||!1===e.options.draggable&&-1!==i.type.indexOf("mouse")))switch(e.touchObject.fingerCount=i.originalEvent&&void 0!==i.originalEvent.touches?i.originalEvent.touches.length:1,e.touchObject.minSwipe=e.listWidth/e.options.touchThreshold,!0===e.options.verticalSwiping&&(e.touchObject.minSwipe=e.listHeight/e.options.touchThreshold),i.data.action){case"start":e.swipeStart(i);break;case"move":e.swipeMove(i);break;case"end":e.swipeEnd(i)}},e.prototype.swipeMove=function(i){var e,t,o,s,n,r,l=this;return n=void 0!==i.originalEvent?i.originalEvent.touches:null,!(!l.dragging||l.scrolling||n&&1!==n.length)&&(e=l.getLeft(l.currentSlide),l.touchObject.curX=void 0!==n?n[0].pageX:i.clientX,l.touchObject.curY=void 0!==n?n[0].pageY:i.clientY,l.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(l.touchObject.curX-l.touchObject.startX,2))),r=Math.round(Math.sqrt(Math.pow(l.touchObject.curY-l.touchObject.startY,2))),!l.options.verticalSwiping&&!l.swiping&&r>4?(l.scrolling=!0,!1):(!0===l.options.verticalSwiping&&(l.touchObject.swipeLength=r),t=l.swipeDirection(),void 0!==i.originalEvent&&l.touchObject.swipeLength>4&&(l.swiping=!0,i.preventDefault()),s=(!1===l.options.rtl?1:-1)*(l.touchObject.curX>l.touchObject.startX?1:-1),!0===l.options.verticalSwiping&&(s=l.touchObject.curY>l.touchObject.startY?1:-1),o=l.touchObject.swipeLength,l.touchObject.edgeHit=!1,!1===l.options.infinite&&(0===l.currentSlide&&"right"===t||l.currentSlide>=l.getDotCount()&&"left"===t)&&(o=l.touchObject.swipeLength*l.options.edgeFriction,l.touchObject.edgeHit=!0),!1===l.options.vertical?l.swipeLeft=e+o*s:l.swipeLeft=e+o*(l.$list.height()/l.listWidth)*s,!0===l.options.verticalSwiping&&(l.swipeLeft=e+o*s),!0!==l.options.fade&&!1!==l.options.touchMove&&(!0===l.animating?(l.swipeLeft=null,!1):void l.setCSS(l.swipeLeft))))},e.prototype.swipeStart=function(i){var e,t=this;if(t.interrupted=!0,1!==t.touchObject.fingerCount||t.slideCount<=t.options.slidesToShow)return t.touchObject={},!1;void 0!==i.originalEvent&&void 0!==i.originalEvent.touches&&(e=i.originalEvent.touches[0]),t.touchObject.startX=t.touchObject.curX=void 0!==e?e.pageX:i.clientX,t.touchObject.startY=t.touchObject.curY=void 0!==e?e.pageY:i.clientY,t.dragging=!0},e.prototype.unfilterSlides=e.prototype.slickUnfilter=function(){var i=this;null!==i.$slidesCache&&(i.unload(),i.$slideTrack.children(this.options.slide).detach(),i.$slidesCache.appendTo(i.$slideTrack),i.reinit())},e.prototype.unload=function(){var e=this;i(".slick-cloned",e.$slider).remove(),e.$dots&&e.$dots.remove(),e.$prevArrow&&e.htmlExpr.test(e.options.prevArrow)&&e.$prevArrow.remove(),e.$nextArrow&&e.htmlExpr.test(e.options.nextArrow)&&e.$nextArrow.remove(),e.$slides.removeClass("slick-slide slick-active slick-visible slick-current").attr("aria-hidden","true").css("width","")}
36741,e.prototype.unslick=function(i){var e=this;e.$slider.trigger("unslick",[e,i]),e.destroy()},e.prototype.updateArrows=function(){var i=this;Math.floor(i.options.slidesToShow/2),!0===i.options.arrows&&i.slideCount>i.options.slidesToShow&&!i.options.infinite&&(i.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false"),i.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false"),0===i.currentSlide?(i.$prevArrow.addClass("slick-disabled").attr("aria-disabled","true"),i.$nextArrow.removeClass("slick-disabled").attr("aria-disabled","false")):i.currentSlide>=i.slideCount-i.options.slidesToShow&&!1===i.options.centerMode?(i.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),i.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")):i.currentSlide>=i.slideCount-1&&!0===i.options.centerMode&&(i.$nextArrow.addClass("slick-disabled").attr("aria-disabled","true"),i.$prevArrow.removeClass("slick-disabled").attr("aria-disabled","false")))},e.prototype.updateDots=function(){var i=this;null!==i.$dots&&(i.$dots.find("li").removeClass("slick-active").end(),i.$dots.find("li").eq(Math.floor(i.currentSlide/i.options.slidesToScroll)).addClass("slick-active"))},e.prototype.visibility=function(){var i=this;i.options.autoplay&&(document[i.hidden]?i.interrupted=!0:i.interrupted=!1)},i.fn.slick=function(){var i,t,o=this,s=arguments[0],n=Array.prototype.slice.call(arguments,1),r=o.length;for(i=0;i<r;i++)if("object"==typeof s||void 0===s?o[i].slick=new e(o[i],s):t=o[i].slick[s].apply(o[i].slick,n),void 0!==t)return t;return o}}); 36742; 36743/*! 36744 Modaal - accessible modals - v0.3.1 36745 by Humaan, for all humans. 36746 http://humaan.com 36747 */ 36748/** 36749 Modaal jQuery Plugin : Accessible Modals 36750 36751 ==== General Options === 36752 type (string) : ajax, inline, image, iframe, confirm. Defaults to 'inline' 36753 animation (string) : Fade, expand, down, up. Defaults to 'fade' 36754 after_callback_delay (integer) : Specify a delay value for the after open callbacks. This is necessary because with the bundled animations 36755 have a set duration in the bundled CSS. Specify a delay of the same amount as the animation duration in so 36756 more accurately fire the after open/close callbacks. Defaults 350, does not apply if animation is 'none', 36757 after open callbacks are dispatched immediately 36758 36759 is_locked (boolean) : Set this to true to disable closing the modal via keypress or clicking the background. Beware that if 36760 type != 'confirm' there will be no interface to dismiss the modal if is_locked = true, you'd have to 36761 programmatically arrange to dismiss the modal. Confirm modals are always locked regardless of this option 36762 Defaults to false 36763 36764 hide_close (boolean) : Set this to true to hide the close modal button. Key press and overlay click will still close the modal. 36765 This method is best used when you want to put a custom close button inside the modal container space. 36766 36767 background (string) : Background overlay style. Defaults to '#000' 36768 overlay_opacity (float) : Background overlay transparency. Defaults to 0.8 36769 overlay_close (boolean) : Set this to false if you want to disable click to close on overlay background. 36770 36771 accessible_title (string) : Accessible title. Default 'Dialog Window' 36772 start_open (boolean) : Set this to true to launch the Modaal window immediately on page open 36773 fullscreen (boolean) : Set this to true to make the modaal fill the entire screen, false will default to own width/height attributes. 36774 custom_class (string) : Fill in this string with a custom class that will be applied to the outer most modal wrapper. 36775 36776 width (integer) : Desired width of the modal. Required for iframe type. Defaults to undefined //TODO 36777 height (integer) : Desired height of the modal. Required for iframe type. Defaults to undefined //TODO 36778 36779 background_scroll (boolean) : Set this to true to enable the page to scroll behind the open modal. 36780 36781 should_open (boolean|function) : Boolean or closure that returns a boolean to determine whether to open the modal or not. 36782 36783 close_text : String for close button text. Available for localisation and alternative languages to be used. 36784 close_aria_label : String for close button aria-label attribute (value that screen readers will read out). Available for localisation and alternative languages to be used. 36785 36786 === Events === 36787 before_open (function) : Callback function executed before modal is opened 36788 after_open (function) : Callback function executed after modal is opened 36789 before_close (function) : Callback function executed before modal is closed 36790 after_close (function) : Callback function executed after modal is closed 36791 source (function(element, src)) : Callback function executed on the default source, it is intended to transform the 36792 source (href in an AJAX modal or iframe). The function passes in the triggering element 36793 as well as the default source depending of the modal type. The default output of the 36794 function is an untransformed default source. 36795 36796 36797 === Confirm Options & Events === 36798 confirm_button_text (string) : Text on the confirm button. Defaults to 'Confirm' 36799 confirm_cancel_button_text (string) : Text on the confirm modal cancel button. Defaults to 'Cancel' 36800 confirm_title (string) : Title for confirm modal. Default 'Confirm Title' 36801 confirm_content (string) : HTML content for confirm message 36802 confirm_callback (function) : Callback function for when the confirm button is pressed as opposed to cancel 36803 confirm_cancel_callback (function) : Callback function for when the cancel button is pressed 36804 36805 36806 === Gallery Options & Events === 36807 gallery_active_class (string) : Active class applied to the currently active image or image slide in a gallery 'gallery_active_item' 36808 before_image_change (function) : Callback function executed before the image slide changes in a gallery modal. Default function( current_item, incoming_item ) 36809 after_image_change (function) : Callback function executed after the image slide changes in a gallery modal. Default function ( current_item ) 36810 36811 36812 === AJAX Options & Events === 36813 loading_content (string) : HTML content for loading message. Default 'Loading …' 36814 loading_class (string) : Class name to be applied while content is loaded via AJAX. Default 'is_loading' 36815 ajax_error_class (string) : Class name to be applied when content has failed to load. Default is 'modaal-error' 36816 ajax_success (function) : Callback for when AJAX content is loaded in 36817 36818 36819 === SOCIAL CONTENT ===
vendor: 13,074 bytes, lines 36820-37225
36820 instagram_id (string) : Unique photo ID for an Instagram photo. 36821 36822*/ 36823( function( $ ) { 36824 36825 var modaal_loading_spinner = '<div class="modaal-loading-spinner"><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div></div>' 36826 36827 var Modaal = { 36828 init : function(options, elem) { 36829 var self = this; 36830 36831 self.dom = $('body'); 36832 36833 self.$elem = $(elem); 36834 self.options = $.extend({}, $.fn.modaal.options, self.$elem.data(), options); 36835 self.xhr = null; 36836 36837 // set up the scope 36838 self.scope = { 36839 is_open: false, 36840 id: 'modaal_' + ( new Date().getTime() ) + ( Math.random().toString(16).substring(2) ) 36841 }; 36842 36843 // add scope attribute to trigger element 36844 self.$elem.attr('data-modaal-scope', self.scope.id); 36845 36846 // private options 36847 self.private_options = { 36848 active_class: 'is_active' 36849 }; 36850 36851 self.lastFocus = null; 36852 36853 // if is_locked 36854 if ( self.options.is_locked || self.options.type == 'confirm' || self.options.hide_close ) { 36855 self.scope.close_btn = ''; 36856 } else { 36857 self.scope.close_btn = '<button type="button" class="modaal-close" id="modaal-close" aria-label="' + self.options.close_aria_label + '"><span>' + self.options.close_text + '</span></button>'; 36858 } 36859 36860 // reset animation_speed 36861 if (self.options.animation === 'none' ){ 36862 self.options.animation_speed = 0; 36863 self.options.after_callback_delay = 0; 36864 } 36865 36866 // On click to open modal 36867 $(elem).on('click.Modaal', function(e) { 36868 e.preventDefault(); 36869 36870 var source; 36871 36872 // Save last active state before modal 36873 self.lastFocus = document.activeElement; 36874 36875 if ( self.options.should_open === false || ( typeof self.options.should_open === 'function' && self.options.should_open() === false ) ) { 36876 return; 36877 } 36878 36879 // CB: before_open 36880 self.options.before_open.call(self, e); 36881 36882 switch (self.options.type) { 36883 case 'inline': 36884 self.create_basic(); 36885 break; 36886 36887 case 'ajax': 36888 source = self.options.source( self.$elem, self.$elem.attr('href') ); 36889 self.fetch_ajax( source ); 36890 break; 36891 36892 case 'confirm': 36893 self.options.is_locked = true; 36894 self.create_confirm(); 36895 break; 36896 36897 case 'image': 36898 self.create_image(); 36899 break; 36900 36901 case 'iframe': 36902 source = self.options.source( self.$elem, self.$elem.attr('href') ); 36903 self.create_iframe( source ); 36904 break; 36905 36906 case 'video': 36907 self.create_video(self.$elem.attr('href')); 36908 break; 36909 36910 case 'instagram': 36911 self.create_instagram(); 36912 break; 36913 } 36914 36915 // call events to be watched (click, tab, keyup, keydown etc.) 36916 self.watch_events(); 36917 36918 }); 36919 36920 36921 // Check for start_open 36922 if (self.options.start_open === true ){ 36923 $(elem).click(); 36924 } 36925 }, 36926 36927 // Watching Modal 36928 // ---------------------------------------------------------------- 36929 watch_events : function() { 36930 var self = this; 36931 36932 self.dom.off('click.Modaal keyup.Modaal keydown.Modaal'); 36933 36934 // Body keydown 36935 self.dom.on('keydown.Modaal', function(e) { 36936 var key = e.keyCode; 36937 var target = e.target; 36938 36939 // look for tab change and reset focus to modal window 36940 // done in keydown so the check fires repeatedly when you hold the tab key down 36941 if (key == 9 && self.scope.is_open) { 36942 if (!$.contains(document.getElementById(self.scope.id), target) ) { 36943 $('#' + self.scope.id).find('*[tabindex="0"]').focus(); 36944 } 36945 } 36946 }); 36947 36948 // Body keyup 36949 self.dom.on('keyup.Modaal', function(e) { 36950 var key = e.keyCode; 36951 var target = e.target; 36952 36953 if ( (e.shiftKey && e.keyCode == 9) && self.scope.is_open) { 36954 // Watch for shift + tab key press. if open shift focus to close button. 36955 if (!$.contains(document.getElementById(self.scope.id), target) ) { 36956 $('#' + self.scope.id).find('.modaal-close').focus(); 36957 } 36958 } 36959 36960 if ( !self.options.is_locked ){ 36961 // On escape key press close modal 36962 if (key == 27 && self.scope.is_open ) { 36963 if ( $(document.activeElement).is('input:not(:checkbox):not(:radio)') ) { 36964 return false; 36965 } 36966 36967 self.modaal_close(); 36968 return; 36969 } 36970 } 36971 36972 // is gallery open and images length is > 1 36973 if ( self.options.type == 'image' ) { 36974 // arrow left for back 36975 if (key == 37 && self.scope.is_open && (!$('#' + self.scope.id + ' .modaal-gallery-prev').hasClass('is_hidden')) ) { 36976 self.gallery_update('prev'); 36977 } 36978 // arrow right for next 36979 if (key == 39 && self.scope.is_open && (!$('#' + self.scope.id + ' .modaal-gallery-next').hasClass('is_hidden')) ) { 36980 self.gallery_update('next'); 36981 } 36982 return; 36983 } 36984 }); 36985 36986 // Body click 36987 self.dom.on('click.Modaal', function(e) { 36988 var trigger = $(e.target); 36989 36990 // General Controls: If it's not locked allow greedy close 36991 if ( !self.options.is_locked ){ 36992 if ( (self.options.overlay_close && trigger.is('.modaal-inner-wrapper')) || trigger.is('.modaal-close') || trigger.closest('.modaal-close').length ) { 36993 self.modaal_close(); 36994 return; 36995 } 36996 } 36997 36998 //Confirm Controls 36999 if ( trigger.is('.modaal-confirm-btn' ) ){ 37000 // if 'OK' button is clicked, run confirm_callback() 37001 if ( trigger.is('.modaal-ok') ) { 37002 self.options.confirm_callback.call(self, self.lastFocus); 37003 } 37004 37005 if ( trigger.is('.modaal-cancel') ) { 37006 self.options.confirm_cancel_callback.call(self, self.lastFocus); 37007 } 37008 self.modaal_close(); 37009 return; 37010 } 37011 37012 // Gallery Controls 37013 if ( trigger.is( '.modaal-gallery-control' ) ){ 37014 // it not active, don't do nuthin! 37015 if ( trigger.hasClass('is_hidden') ) { 37016 return; 37017 } 37018 37019 // trigger previous 37020 if ( trigger.is('.modaal-gallery-prev') ) { 37021 self.gallery_update('prev'); 37022 } 37023 // trigger next 37024 if ( trigger.is('.modaal-gallery-next') ) { 37025 self.gallery_update('next'); 37026 } 37027 return; 37028 } 37029 }); 37030 }, 37031 37032 // Append markup into DOM 37033 build_modal : function(content) { 37034 var self = this; 37035 37036 // if is instagram 37037 var igClass = ''; 37038 if ( self.options.type == 'instagram' ) { 37039 igClass = ' modaal-instagram'; 37040 } 37041 37042 var wrap_class = (self.options.type == 'video') ? 'modaal-video-wrap' : 'modaal-content'; 37043 37044 /* 37045 modaal-start_none : fully hidden via display:none; 37046 modaal-start_fade : hidden via opacity:0 37047 modaal-start_slidedown : ... 37048 37049 */ 37050 var animation_class; 37051 switch ( self.options.animation ) { 37052 case 'fade' : 37053 animation_class = ' modaal-start_fade'; 37054 break; 37055 case 'slide-down' : 37056 animation_class = ' modaal-start_slidedown'; 37057 break; 37058 default : 37059 animation_class = ' modaal-start_none' 37060 } 37061 37062 // fullscreen check 37063 var fullscreen_class = ''; 37064 if ( self.options.fullscreen ) { 37065 fullscreen_class = ' modaal-fullscreen'; 37066 } 37067 37068 // custom class check 37069 if ( self.options.custom_class !== '' || typeof(self.options.custom_class) !== 'undefined' ) { 37070 self.options.custom_class = ' ' + self.options.custom_class; 37071 } 37072 37073 // if width and heights exists and is typeof number 37074 var dimensionsStyle = ''; 37075 if ( self.options.width && self.options.height && typeof self.options.width == 'number' && typeof self.options.height == 'number' ) { 37076 // if width and height exist, and they are both numbers 37077 dimensionsStyle = ' style="max-width:' + self.options.width + 'px;height:' + self.options.height + 'px;overflow:auto;"'; 37078 } else if ( self.options.width && typeof self.options.width == 'number' ) { 37079 // if only width 37080 dimensionsStyle = ' style="max-width:' + self.options.width + 'px;"'; 37081 } else if ( self.options.height && typeof self.options.height == 'number' ) { 37082 // if only height 37083 dimensionsStyle = ' style="height:' + self.options.height + 'px;overflow:auto;"'; 37084 } 37085 37086 // Reset dimensions style (width and height) for certain types 37087 if ( self.options.type == 'image' || self.options.type == 'video' || self.options.type == 'instagram' || self.options.fullscreen ) { 37088 dimensionsStyle = ''; 37089 } 37090 37091 //var build_markup = '<div class="modaal-wrapper modaal-start_fade' + igClass + '" id="' + self.scope.id + '"><div class="modaal-outer-wrapper"><div class="modaal-inner-wrapper">'; 37092 var build_markup = '<div class="modaal-wrapper modaal-' + self.options.type + animation_class + igClass + fullscreen_class + self.options.custom_class + '" id="' + self.scope.id + '"><div class="modaal-outer-wrapper"><div class="modaal-inner-wrapper">'; 37093 37094 // hide if video 37095 if (self.options.type != 'video') { 37096 build_markup += '<div class="modaal-container"' + dimensionsStyle + '>'; 37097 } 37098 37099 // add the guts of the content 37100 build_markup += '<div class="' + wrap_class + ' modaal-focus" aria-hidden="false" aria-label="' + self.options.accessible_title + ' (Press escape to close)" role="dialog">'; 37101 37102 // If it's inline type, we want to clone content instead of dropping it straight in 37103 if (self.options.type == 'inline') { 37104 build_markup += '<div class="modaal-content-container"></div>'; 37105 } else { 37106 // Drop in the content if it's not inline 37107 build_markup += content; 37108 } 37109 37110 // close wrap_class 37111 build_markup += '</div>' + self.scope.close_btn; 37112 37113 // hide if video 37114 if (self.options.type != 'video') { 37115 build_markup += '</div>'; 37116 } 37117 37118 // close off modaal-wrapper 37119 build_markup += '</div></div></div>'; 37120 37121 // append ajax modal markup to dom 37122 self.dom.append(build_markup); 37123 37124 // if inline, clone content into space 37125 if (self.options.type == 'inline') { 37126 content.appendTo('#' + self.scope.id + ' .modaal-content-container'); 37127 } 37128 37129 // Trigger overlay show (which triggers modal show) 37130 self.modaal_overlay('show'); 37131 }, 37132 37133 // Create Basic Inline Modal 37134 // ---------------------------------------------------------------- 37135 create_basic : function() { 37136 var self = this; 37137 // if $elem is a link, then href points to the target, otherwise assume target was passed in initially 37138 var target = (self.$elem.is('[href]')) ? $(self.$elem.attr('href')) : self.$elem; 37139 var content = ''; 37140 37141 if (target.length) { 37142 content = target.contents().clone(true,true); 37143 target.empty(); 37144 } else { 37145 content = 'Content could not be loaded. Please check the source and try again.'; 37146 } 37147 37148 // now push content into markup 37149 self.build_modal(content); 37150 }, 37151 37152 // Create Instagram Modal 37153 // ---------------------------------------------------------------- 37154 create_instagram : function() { 37155 var self = this; 37156 var id = self.options.instagram_id; 37157 var content = ''; 37158 37159 var error_msg = 'Instagram photo couldn\'t be loaded, please check the embed code and try again.'; 37160 37161 self.build_modal('<div class="modaal-content-container' + ( self.options.loading_class != '' ? ' ' + self.options.loading_class : '' ) + '">' + self.options.loading_content + '</div>' ); 37162 37163 // ID exists, is not empty null or undefined. 37164 if ( id != '' && id !== null && id !== undefined ) { 37165 // set up oembed url 37166 var ig_url = 'https://api.instagram.com/oembed?url=http://instagr.am/p/' + id + '/'; 37167 37168 $.ajax({ 37169 url: ig_url, 37170 dataType: "jsonp", 37171 cache: false, 37172 success: function (data) { 37173 // set up the new content 37174 content = data.html; 37175 37176 // now set location for new content 37177 var target = $('#' + self.scope.id + ' .modaal-content-container'); 37178 if ( target.length > 0) { 37179 // add HTML into target region 37180 target.removeClass( self.options.loading_class ); 37181 target.html(content); 37182 37183 // now trigger an instagram refresh 37184 window.instgrm.Embeds.process(); 37185 } 37186 }, 37187 error: function() { 37188 content = error_msg; 37189 37190 // now set location for new content 37191 var target = $('#' + self.scope.id + ' .modaal-content-container'); 37192 if ( target.length > 0) { 37193 target.removeClass( self.options.loading_class ).addClass( self.options.ajax_error_class ); 37194 target.html(content); 37195 } 37196 } 37197 }); 37198 37199 } else { 37200 content = error_msg; 37201 } 37202 37203 return false; 37204 }, 37205 37206 // Fetch Ajax Data 37207 // ---------------------------------------------------------------- 37208 fetch_ajax : function(url) { 37209 var self = this; 37210 var content = ''; 37211 37212 // If no accessible title, set it to 'Dialog Window' 37213 if ( self.options.accessible_title == null ) { 37214 self.options.accessible_title = 'Dialog Window' 37215 } 37216 37217 if ( self.xhr !== null ){ 37218 self.xhr.abort(); 37219 self.xhr = null; 37220 } 37221 37222 self.build_modal('<div class="modaal-content-container' + ( self.options.loading_class != '' ? ' ' + self.options.loading_class : '' ) + '">' + self.options.loading_content + '</div>' ); 37223 37224 self.xhr = $.ajax(url, { 37225 success: function(data) {
37226 // content fetch is successful so push it into markup 37227 var target = $('#' + self.scope.id).find('.modaal-content-container'); 37228 if ( target.length > 0){ 37229 target.removeClass( self.options.loading_class ); 37230 target.html( data ); 37231 37232 self.options.ajax_success.call(self, target); 37233 } 37234 }, 37235 error: function( xhr ) { 37236 // There were some errors so return an error message 37237 if ( xhr.statusText == 'abort' ){ 37238 return; 37239 } 37240 37241 var target = $('#' + self.scope.id + ' .modaal-content-container'); 37242 if ( target.length > 0){ 37243 target.removeClass( self.options.loading_class ).addClass( self.options.ajax_error_class ); 37244 target.html( 'Content could not be loaded. Please check the source and try again.' ); 37245 } 37246 } 37247 }); 37248 }, 37249 37250 // Create Confirm Modal 37251 // ---------------------------------------------------------------- 37252 create_confirm : function() { 37253 var self = this; 37254 var content; 37255 37256 content = '<div class="modaal-content-container">' + 37257 '<h1 id="modaal-title">' + self.options.confirm_title + '</h1>' + 37258 '<div class="modaal-confirm-content">' + self.options.confirm_content + '</div>' + 37259 '<div class="modaal-confirm-wrap">' + 37260 '<button type="button" class="modaal-confirm-btn modaal-ok" aria-label="Confirm">' + self.options.confirm_button_text + '</button>' + 37261 '<button type="button" class="modaal-confirm-btn modaal-cancel" aria-label="Cancel">' + self.options.confirm_cancel_button_text + '</button>' + 37262 '</div>' + 37263 '</div>' + 37264 '</div>'; 37265 37266 // now push content into markup 37267 self.build_modal(content); 37268 }, 37269 37270 // Create Image/Gallery Modal 37271 // ---------------------------------------------------------------- 37272 create_image : function() { 37273 var self = this; 37274 var content; 37275 37276 var modaal_image_markup = ''; 37277 var gallery_total; 37278 var prev_btn = '<button type="button" class="modaal-gallery-control modaal-gallery-prev" id="modaal-gallery-prev" aria-label="Previous image (use left arrow to change)"><span>Previous Image</span></button>'; 37279 var next_btn = '<button type="button" class="modaal-gallery-control modaal-gallery-next" id="modaal-gallery-next" aria-label="Next image (use right arrow to change)"><span>Next Image</span></button>'; 37280 37281 // If has rel attribute 37282 if ( self.$elem.is('[rel]') ) { 37283 // find gallery rel 37284 var gallery_group = self.$elem.attr('rel'); 37285 var gallery_group_items = $('[rel="' + gallery_group + '"]'); 37286 37287 // remove any previous active attribute to any in the group 37288 gallery_group_items.removeAttr('data-gallery-active', 'is_active'); 37289 // add active attribute to the item clicked 37290 self.$elem.attr('data-gallery-active', 'is_active'); 37291 37292 // how many in the rel grouping are there (-1 to connect with each function starting with 0) 37293 gallery_total = gallery_group_items.length - 1; 37294 37295 // prepare array for gallery data 37296 var gallery = []; 37297 37298 // start preparing markup 37299 modaal_image_markup = '<div class="modaal-gallery-item-wrap">'; 37300 37301 // loop each grouping item and push it into our gallery array 37302 gallery_group_items.each(function(i, item) { 37303 // setup default content 37304 var img_src = ''; 37305 var img_alt = ''; 37306 var img_description = ''; 37307 var img_active = false; 37308 37309 var data_modaal_desc = item.getAttribute('data-modaal-desc'); 37310 var data_item_active = item.getAttribute('data-gallery-active'); 37311 37312 // is it an img SRC or link HREF value 37313 if ( item.href !== '' || item.href !== undefined ) { 37314 img_src = item.href; 37315 } else if ( item.src !== '' || item.src !== undefined ) { 37316 img_src = item.src; 37317 } 37318 37319 // Does it have a modaal description 37320 if ( data_modaal_desc != '' && data_modaal_desc !== null && data_modaal_desc !== undefined ) { 37321 img_alt = data_modaal_desc; 37322 img_description = '<div class="modaal-gallery-label"><span class="modaal-accessible-hide">Image ' + (i+1) + ' - </span>' + data_modaal_desc + '</div>' 37323 } else { 37324 img_description = '<div class="modaal-gallery-label"><span class="modaal-accessible-hide">Image ' + (i+1) + '</span></div>'; 37325 } 37326 37327 // is it the active item 37328 if ( data_item_active ) { 37329 img_active = true 37330 } 37331 37332 // set new object for values we want 37333 var gallery_item = { 37334 'url': img_src, 37335 'alt': img_alt, 37336 'rawdesc': data_modaal_desc, 37337 'desc': img_description, 37338 'active': img_active 37339 }; 37340 37341 // push object into gallery array 37342 gallery.push( gallery_item ); 37343 }); 37344 37345 // now loop through all items in the gallery and build up the markup 37346 for (var i = 0; i < gallery.length; i++) { 37347 // Set default active class, then check if array item active is true and update string for class 37348 var is_active = ''; 37349 var aria_label = gallery[i].rawdesc ? 'Image: ' + gallery[i].rawdesc : 'Image ' + i + ' no description'; 37350 37351 if ( gallery[i].active ) { 37352 is_active = ' ' + self.private_options.active_class; 37353 } 37354 37355 // for each item build up the markup 37356 modaal_image_markup += '<div class="modaal-gallery-item gallery-item-' + i + is_active + '" aria-label="' + aria_label + '">' + 37357 '<img src="' + gallery[i].url + '" alt=" " style="width:100%">' + 37358 gallery[i].desc + 37359 '</div>'; 37360 } 37361 37362 // close off the markup for the gallery and add next/previous buttons 37363 modaal_image_markup += '</div>' + prev_btn + next_btn; 37364 } else { 37365 // This is only a single gallery item so let's grab the necessary values 37366 37367 // Setup selected image 37368 var this_img_src = self.$elem.attr('href'); 37369 var this_img_alt_txt = ''; 37370 var this_img_alt = ''; 37371 var aria_label = ''; 37372 37373 if ( self.$elem.attr('data-modaal-desc') ) { 37374 aria_label = self.$elem.attr('data-modaal-desc'); 37375 this_img_alt_txt = self.$elem.attr('data-modaal-desc'); 37376 this_img_alt = '<div class="modaal-gallery-label"><span class="modaal-accessible-hide">Image - </span>' + this_img_alt_txt + '</div>'; 37377 } else { 37378 aria_label = "Image with no description"; 37379 } 37380 37381 // build up the html 37382 modaal_image_markup = '<div class="modaal-gallery-item is_active" aria-label="' + aria_label + '">' + 37383 '<img src="' + this_img_src + '" alt=" " style="width:100%">' + 37384 this_img_alt + 37385 '</div>'; 37386 } 37387 37388 // Update content variable 37389 content = modaal_image_markup; 37390 37391 // now push content into markup 37392 self.build_modal(content); 37393 37394 // setup next & prev buttons 37395 if ( $('.modaal-gallery-item.is_active').is('.gallery-item-0') ) { 37396 $('.modaal-gallery-prev').hide(); 37397 } 37398 if ( $('.modaal-gallery-item.is_active').is('.gallery-item-' + gallery_total) ) { 37399 $('.modaal-gallery-next').hide(); 37400 } 37401 }, 37402 37403 // Gallery Change Image 37404 // ---------------------------------------------------------------- 37405 gallery_update : function(direction) { 37406 var self = this; 37407 var this_gallery = $('#' + self.scope.id); 37408 var this_gallery_item = this_gallery.find('.modaal-gallery-item'); 37409 var this_gallery_total = this_gallery_item.length - 1; 37410 37411 // if single item, don't proceed 37412 if ( this_gallery_total == 0 ) { 37413 return false; 37414 } 37415 37416 var prev_btn = this_gallery.find('.modaal-gallery-prev'), 37417 next_btn = this_gallery.find('.modaal-gallery-next'); 37418 37419 var duration = 250; 37420 37421 var new_img_w = 0, 37422 new_img_h = 0; 37423
vendor: 8,985 bytes, lines 37424-37686
37424 // CB: Before image change 37425 var current_item = this_gallery.find( '.modaal-gallery-item.' + self.private_options.active_class ), 37426 incoming_item = ( direction == 'next' ? current_item.next( '.modaal-gallery-item' ) : current_item.prev( '.modaal-gallery-item' ) ); 37427 self.options.before_image_change.call(self, current_item, incoming_item); 37428 37429 // stop change if at start of end 37430 if ( direction == 'prev' && this_gallery.find('.gallery-item-0').hasClass('is_active') ) { 37431 return false; 37432 } else if ( direction == 'next' && this_gallery.find('.gallery-item-' + this_gallery_total).hasClass('is_active') ) { 37433 return false; 37434 } 37435 37436 37437 // lock dimensions 37438 current_item.stop().animate({ 37439 opacity: 0 37440 }, duration, function(){ 37441 // Move to appropriate image 37442 incoming_item.addClass('is_next').css({ 37443 'position': 'absolute', 37444 'display': 'block', 37445 'opacity': 0 37446 }); 37447 37448 // Collect doc width 37449 var doc_width = $(document).width(); 37450 var width_threshold = doc_width > 1140 ? 280 : 50; 37451 37452 // start toggle to 'is_next' 37453 new_img_w = this_gallery.find('.modaal-gallery-item.is_next').width(); 37454 new_img_h = this_gallery.find('.modaal-gallery-item.is_next').height(); 37455 37456 var new_natural_w = this_gallery.find('.modaal-gallery-item.is_next img').prop('naturalWidth'); 37457 var new_natural_h = this_gallery.find('.modaal-gallery-item.is_next img').prop('naturalHeight'); 37458 37459 // if new image is wider than doc width 37460 if ( new_natural_w > (doc_width - width_threshold) ) { 37461 // set new width just below doc width 37462 new_img_w = doc_width - width_threshold; 37463 37464 // Set temp widths so we can calulate the correct height; 37465 this_gallery.find('.modaal-gallery-item.is_next').css({ 'width': new_img_w }); 37466 this_gallery.find('.modaal-gallery-item.is_next img').css({ 'width': new_img_w }); 37467 37468 // Set new height variable 37469 new_img_h = this_gallery.find('.modaal-gallery-item.is_next').find('img').height(); 37470 } else { 37471 // new img is not wider than screen, so let's set the new dimensions 37472 new_img_w = new_natural_w; 37473 new_img_h = new_natural_h; 37474 } 37475 37476 // resize gallery region 37477 this_gallery.find('.modaal-gallery-item-wrap').stop().animate({ 37478 'width': new_img_w, 37479 'height': new_img_h 37480 }, duration, function() { 37481 // hide old active image 37482 current_item.removeClass(self.private_options.active_class + ' ' + self.options.gallery_active_class).removeAttr('style'); 37483 current_item.find('img').removeAttr('style'); 37484 37485 // show new image 37486 incoming_item.addClass(self.private_options.active_class + ' ' + self.options.gallery_active_class).removeClass('is_next').css('position',''); 37487 37488 // animate in new image (now has the normal is_active class 37489 incoming_item.stop().animate({ 37490 opacity: 1 37491 }, duration, function(){ 37492 $(this).removeAttr('style').css({ 37493 'width': '100%' 37494 }); 37495 $(this).find('img').css('width', '100%'); 37496 37497 // remove dimension lock 37498 this_gallery.find('.modaal-gallery-item-wrap').removeAttr('style'); 37499 37500 // CB: After image change 37501 self.options.after_image_change.call( self, incoming_item ); 37502 }); 37503 37504 // Focus on the new gallery item 37505 this_gallery.find('.modaal-gallery-item').removeAttr('tabindex'); 37506 this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class + '').attr('tabindex', '0').focus(); 37507 37508 // hide/show next/prev 37509 if ( this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class).is('.gallery-item-0') ) { 37510 prev_btn.stop().animate({ 37511 opacity: 0 37512 }, 150, function(){ 37513 $(this).hide(); 37514 }); 37515 } else { 37516 prev_btn.stop().css({ 37517 'display': 'block', 37518 'opacity': prev_btn.css('opacity') 37519 }).animate({ 37520 opacity: 1 37521 }, 150); 37522 } 37523 if ( this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class).is('.gallery-item-' + this_gallery_total) ) { 37524 next_btn.stop().animate({ 37525 opacity: 0 37526 }, 150, function(){ 37527 $(this).hide(); 37528 }); 37529 } else { 37530 next_btn.stop().css({ 37531 'display': 'block', 37532 'opacity': prev_btn.css('opacity') 37533 }).animate({ 37534 opacity: 1 37535 }, 150); 37536 } 37537 }); 37538 }); 37539 }, 37540 37541 // Create Video Modal 37542 // ---------------------------------------------------------------- 37543 create_video : function(url) { 37544 var self = this; 37545 var content; 37546 37547 // video markup 37548 content = '<iframe src="' + url + '" class="modaal-video-frame" frameborder="0" allowfullscreen></iframe>'; 37549 37550 // now push content into markup 37551 self.build_modal('<div class="modaal-video-container">' + content + '</div>'); 37552 }, 37553 37554 // Create iFrame Modal 37555 // ---------------------------------------------------------------- 37556 create_iframe : function(url) { 37557 var self = this; 37558 var content; 37559 37560 if ( self.options.width !== null || self.options.width !== undefined || self.options.height !== null || self.options.height !== undefined ) { 37561 // video markup 37562 content = '<iframe src="' + url + '" class="modaal-iframe-elem" frameborder="0" allowfullscreen></iframe>'; 37563 } else { 37564 content = '<div class="modaal-content-container">Please specify a width and height for your iframe</div>'; 37565 } 37566 37567 // now push content into markup 37568 self.build_modal(content); 37569 }, 37570 37571 // Open Modaal 37572 // ---------------------------------------------------------------- 37573 modaal_open : function() { 37574 var self = this; 37575 var modal_wrapper = $( '#' + self.scope.id ); 37576 var animation_type = self.options.animation; 37577 37578 if (animation_type === 'none' ){ 37579 modal_wrapper.removeClass('modaal-start_none'); 37580 self.options.after_open.call(self, modal_wrapper); 37581 } 37582 37583 // Open with fade 37584 if (animation_type === 'fade') { 37585 modal_wrapper.removeClass('modaal-start_fade'); 37586 } 37587 37588 // Open with slide down 37589 if (animation_type === 'slide-down') { 37590 modal_wrapper.removeClass('modaal-start_slide_down'); 37591 } 37592 37593 var focusTarget = modal_wrapper; 37594 37595 // Switch focusTarget tabindex (switch from other modal if exists) 37596 $('.modaal-wrapper *[tabindex=0]').removeAttr('tabindex'); 37597 37598 if ( self.options.type == 'image' ) { 37599 focusTarget = $('#' + self.scope.id).find('.modaal-gallery-item.' + self.private_options.active_class); 37600 37601 } else if ( modal_wrapper.find('.modaal-iframe-elem').length ) { 37602 focusTarget = modal_wrapper.find('.modaal-iframe-elem'); 37603 37604 } else if ( modal_wrapper.find('.modaal-video-wrap').length ) { 37605 focusTarget = modal_wrapper.find('.modaal-video-wrap'); 37606 37607 } else { 37608 focusTarget = modal_wrapper.find('.modaal-focus'); 37609 37610 } 37611 37612 // now set the focus 37613 focusTarget.attr('tabindex', '0').focus(); 37614 37615 // Run after_open 37616 if (animation_type !== 'none') { 37617 // CB: after_open 37618 setTimeout(function() { 37619 self.options.after_open.call(self, modal_wrapper) 37620 }, self.options.after_callback_delay); 37621 } 37622 }, 37623 37624 // Close Modal 37625 // ---------------------------------------------------------------- 37626 modaal_close : function() { 37627 var self = this; 37628 var modal_wrapper = $( '#' + self.scope.id ); 37629 37630 // CB: before_close 37631 self.options.before_close.call(self, modal_wrapper); 37632 37633 if (self.xhr !== null){ 37634 self.xhr.abort(); 37635 self.xhr = null; 37636 } 37637 37638 // Now we close the modal 37639 if (self.options.animation === 'none' ){ 37640 modal_wrapper.addClass('modaal-start_none'); 37641 } 37642 37643 // Close with fade 37644 if (self.options.animation === 'fade') { 37645 modal_wrapper.addClass('modaal-start_fade'); 37646 } 37647 37648 // Close with slide up (using initial slide down) 37649 if (self.options.animation === 'slide-down') { 37650 modal_wrapper.addClass('modaal-start_slide_down'); 37651 } 37652 37653 // CB: after_close and remove 37654 setTimeout(function() { 37655 // clone inline content back to origin place 37656 if (self.options.type == 'inline') { 37657 $('#' + self.scope.id + ' .modaal-content-container').contents().clone(true,true).appendTo( self.$elem.attr('href') ) 37658 } 37659 // remove markup from dom 37660 modal_wrapper.remove(); 37661 // CB: after_close 37662 self.options.after_close.call(self); 37663 // scope is now closed 37664 self.scope.is_open = false; 37665 37666 }, self.options.after_callback_delay); 37667 37668 // Call overlay hide 37669 self.modaal_overlay('hide'); 37670 37671 // Roll back to last focus state before modal open. If was closed programmatically, this might not be set 37672 if (self.lastFocus != null) { 37673 self.lastFocus.focus(); 37674 } 37675 }, 37676 37677 // Overlay control (accepts action for show or hide) 37678 // ---------------------------------------------------------------- 37679 modaal_overlay : function(action) { 37680 var self = this; 37681 37682 if (action == 'show') { 37683 // Modal is open so update scope 37684 self.scope.is_open = true; 37685 37686 // set body to overflow hidden if background_scroll is false
37687 if (! self.options.background_scroll) { 37688 self.dom.addClass('modaal-noscroll'); 37689 } 37690 37691 // append modaal overlay 37692 self.dom.append('<div class="modaal-overlay" id="' + self.scope.id + '_overlay"></div>'); 37693 37694 // now show 37695 $('#' + self.scope.id + '_overlay').css('background', self.options.background).stop().animate({ 37696 opacity: self.options.overlay_opacity 37697 }, self.options.animation_speed, function(){ 37698 // now open the modal 37699 self.modaal_open(); 37700 }); 37701 37702 } else if (action == 'hide') { 37703 // remove body overflow lock 37704 self.dom.removeClass('modaal-noscroll'); 37705 37706 // now hide the overlay 37707 $('#' + self.scope.id + '_overlay').stop().animate({ 37708 opacity: 0 37709 }, self.options.animation_speed, function(){ 37710 // remove overlay from dom 37711 $(this).remove(); 37712 }); 37713 } 37714 } 37715 }; 37716 37717 // Declare the modaal jQuery method 37718 // ------------------------------------------------------------ 37719 $.fn.modaal = function(options) { 37720 return this.each(function () { 37721 var existing_modaal = $(this).data('modaal'); 37722 37723 if ( existing_modaal ){ 37724 // Checking for string value, used for methods 37725 if (typeof(options) == 'string'){ 37726 switch (options) { 37727 case 'close': 37728 existing_modaal.modaal_close(); 37729 break; 37730 } 37731 } 37732 } else { 37733 // Not a string, so let's setup the modal ready to use 37734 var modaal = Object.create(Modaal); 37735 modaal.init(options, this); 37736 $.data(this, "modaal", modaal); 37737 } 37738 }); 37739 }; 37740 37741 // Default options 37742 // ------------------------------------------------------------ 37743 $.fn.modaal.options = { 37744 37745 //General 37746 type : 'inline', 37747 animation : 'fade', 37748 animation_speed : 300, 37749 after_callback_delay : 350, 37750 is_locked : false, 37751 hide_close: false, 37752 background: '#000', 37753 overlay_opacity: '0.8', 37754 overlay_close: true, 37755 accessible_title: 'Dialog Window', 37756 start_open: false, 37757 fullscreen: false, 37758 custom_class: '', 37759 background_scroll: false, 37760 should_open: true, 37761 close_text: 'Close', 37762 close_aria_label: 'Close (Press escape to close)', 37763 width: null, 37764 height: null, 37765 37766 //Events 37767 before_open : function(){}, 37768 after_open : function(){}, 37769 before_close : function(){}, 37770 after_close : function(){}, 37771 source : function( element, src ){ 37772 return src; 37773 }, 37774 37775 //Confirm Modal 37776 confirm_button_text: 'Confirm', // text on confirm button 37777 confirm_cancel_button_text: 'Cancel', 37778 confirm_title: 'Confirm Title', // title for confirm modal 37779 confirm_content: '<p>This is the default confirm dialog content. Replace me through the options</p>', // html for confirm message 37780 confirm_callback: function() {}, 37781 confirm_cancel_callback: function() {}, 37782 37783 37784 //Gallery Modal 37785 gallery_active_class: 'gallery_active_item', 37786 before_image_change: function( current_item, incoming_item ) {}, 37787 after_image_change: function( current_item ) {}, 37788 37789 //Ajax Modal 37790 loading_content : modaal_loading_spinner, 37791 loading_class : 'is_loading', 37792 ajax_error_class : 'modaal-error', 37793 ajax_success : function(){}, 37794 37795 //Instagram 37796 instagram_id : null 37797 }; 37798 37799 // On body load (or now, if already loaded), init any modaals defined inline 37800 // Ensure this is done after $.fn.modaal and default options are declared 37801 // ---------------------------------------------------------------- 37802 $(function(){ 37803 var single_modaal = $('.modaal'); 37804 37805 if ( single_modaal.length ) { 37806 single_modaal.each(function() { 37807 var self = $(this); 37808 37809 // new empty options 37810 var options = {}; 37811 var inline_options = false; 37812 37813 // option: type 37814 if ( self.attr('data-modaal-type') ) { 37815 inline_options = true; 37816 options.type = self.attr('data-modaal-type'); 37817 } 37818 37819 // option: animation 37820 if ( self.attr('data-modaal-animation') ) { 37821 inline_options = true; 37822 options.animation = self.attr('data-modaal-animation'); 37823 } 37824 37825 // option: animation_speed 37826 if ( self.attr('data-modaal-animation-speed') ) { 37827 inline_options = true; 37828 options.animation_speed = self.attr('data-modaal-animation-speed'); 37829 } 37830 37831 // option: after_callback_delay 37832 if ( self.attr('data-modaal-after-callback-delay') ) { 37833 inline_options = true; 37834 options.after_callback_delay = self.attr('data-modaal-after-callback-delay'); 37835 } 37836 37837 // option: after_callback_delay 37838 if ( self.attr('data-modaal-is-locked') ) { 37839 inline_options = true; 37840 options.is_locked = (self.attr('data-modaal-is-locked') === 'true' ? true : false); 37841 } 37842 37843 // option: hide_close 37844 if ( self.attr('data-modaal-hide-close') ) { 37845 inline_options = true; 37846 options.hide_close = (self.attr('data-modaal-hide-close') === 'true' ? true : false); 37847 } 37848 37849 // option: background 37850 if ( self.attr('data-modaal-background') ) { 37851 inline_options = true; 37852 options.background = self.attr('data-modaal-background'); 37853 } 37854 37855 // option: overlay_opacity 37856 if ( self.attr('data-modaal-overlay-opacity') ) { 37857 inline_options = true; 37858 options.overlay_opacity = self.attr('data-modaal-overlay-opacity'); 37859 } 37860 37861 // option: overlay_close 37862 if ( self.attr('data-modaal-overlay-close') ) { 37863 inline_options = true; 37864 options.overlay_close = (self.attr('data-modaal-overlay-close') === 'false' ? false : true); 37865 } 37866 37867 // option: accessible_title 37868 if ( self.attr('data-modaal-accessible-title') ) { 37869 inline_options = true; 37870 options.accessible_title = self.attr('data-modaal-accessible-title'); 37871 } 37872 37873 // option: start_open 37874 if ( self.attr('data-modaal-start-open') ) { 37875 inline_options = true; 37876 options.start_open = (self.attr('data-modaal-start-open') === 'true' ? true : false); 37877 } 37878 37879 // option: fullscreen 37880 if ( self.attr('data-modaal-fullscreen') ) { 37881 inline_options = true; 37882 options.fullscreen = (self.attr('data-modaal-fullscreen') === 'true' ? true : false); 37883 } 37884 37885 // option: custom_class 37886 if ( self.attr('data-modaal-custom-class') ) { 37887 inline_options = true; 37888 options.custom_class = self.attr('data-modaal-custom-class'); 37889 } 37890 37891 // option: close_text 37892 if ( self.attr('data-modaal-close-text') ) { 37893 inline_options = true; 37894 options.close_text = self.attr('data-modaal-close-text'); 37895 } 37896 37897 // option: close_aria_label 37898 if ( self.attr('data-modaal-close-aria-label') ) { 37899 inline_options = true; 37900 options.close_aria_label = self.attr('data-modaal-close-aria-label'); 37901 } 37902 37903 // option: background_scroll 37904 if ( self.attr('data-modaal-background-scroll') ) { 37905 inline_options = true; 37906 options.background_scroll = (self.attr('data-modaal-background-scroll') === 'true' ? true : false); 37907 } 37908 37909 // option: width 37910 if ( self.attr('data-modaal-width') ) { 37911 inline_options = true; 37912 options.width = parseInt( self.attr('data-modaal-width') ); 37913 } 37914 37915 // option: height 37916 if ( self.attr('data-modaal-height') ) { 37917 inline_options = true; 37918 options.height = parseInt( self.attr('data-modaal-height') ); 37919 } 37920 37921 // option: confirm_button_text 37922 if ( self.attr('data-modaal-confirm-button-text') ) { 37923 inline_options = true; 37924 options.confirm_button_text = self.attr('data-modaal-confirm-button-text'); 37925 } 37926 37927 // option: confirm_cancel_button_text 37928 if ( self.attr('data-modaal-confirm-cancel-button-text') ) { 37929 inline_options = true; 37930 options.confirm_cancel_button_text = self.attr('data-modaal-confirm-cancel-button-text'); 37931 } 37932 37933 // option: confirm_title 37934 if ( self.attr('data-modaal-confirm-title') ) { 37935 inline_options = true; 37936 options.confirm_title = self.attr('data-modaal-confirm-title'); 37937 } 37938 37939 // option: confirm_content 37940 if ( self.attr('data-modaal-confirm-content') ) { 37941 inline_options = true; 37942 options.confirm_content = self.attr('data-modaal-confirm-content'); 37943 } 37944 37945 // option: gallery_active_class 37946 if ( self.attr('data-modaal-gallery-active-class') ) { 37947 inline_options = true; 37948 options.gallery_active_class = self.attr('data-modaal-gallery-active-class'); 37949 } 37950 37951 // option: loading_content 37952 if ( self.attr('data-modaal-loading-content') ) { 37953 inline_options = true; 37954 options.loading_content = self.attr('data-modaal-loading-content'); 37955 } 37956 37957 // option: loading_class 37958 if ( self.attr('data-modaal-loading-class') ) { 37959 inline_options = true; 37960 options.loading_class = self.attr('data-modaal-loading-class'); 37961 } 37962 37963 // option: ajax_error_class 37964 if ( self.attr('data-modaal-ajax-error-class') ) { 37965 inline_options = true; 37966 options.ajax_error_class = self.attr('data-modaal-ajax-error-class'); 37967 } 37968 37969 // option: start_open 37970 if ( self.attr('data-modaal-instagram-id') ) { 37971 inline_options = true; 37972 options.instagram_id = self.attr('data-modaal-instagram-id'); 37973 } 37974 37975 // now set it up for the trigger, but only if inline_options is true 37976 if ( inline_options ) { 37977 self.modaal(options); 37978 } 37979 }); 37980 } 37981 }); 37982 37983} ( jQuery, window, document ) ); 37984; 37985/// <reference path="../_references.js" /> 37986 37987Agility.RegisterNamespace("APP.Core"); 37988Agility.RegisterNamespace("APP.Data"); 37989Agility.RegisterNamespace("APP.ViewModels"); 37990Agility.RegisterNamespace("APP.Router"); 37991 37992var CORE = APP.Core, 37993 VM = APP.ViewModels, 37994 DATA = APP.Data 37995 37996///////////////////////// 37997//UTILITIES 37998///////////////////////// 37999 38000 38001CORE.Keys = { 38002 AgilityPageAPIBasePath: '/AgilityPage/GetPage?path=' 38003}; 38004 38005CORE.DateFormatString = { 38006 //DateWithTime: 'MMMM Do YYYY, h:mm:ss a', // August 4th 2016, 8:29:34 am, 38007 //DateOnly: "MMM Do YY", // Aug 4th 16 38008 //DateTimeCompact: 'MM/DD/YY h:mm a' //08/04/2016 8:29 am 38009};
38010 38011CORE.RegEx = { 38012 //FirstAndLastName: /^[a-z ,.'-]+$/i, 38013 //PostalZipCode: /^[ABCEGHJKLMNPRSTVXY][0-9][ABCEGHJKLMNPRSTVWXYZ][0-9][ABCEGHJKLMNPRSTVWXYZ][0-9]$|^\d{5}(?:[-\s]\d{4})?$/i 38014}; 38015 38016CORE.MakeFriendlyString = function (s) { 38017 if (s) { 38018 var r = s.toLowerCase(); 38019 r = r.replace(new RegExp("\\s", 'g'), "-"); 38020 r = r.replace(new RegExp("[à áâãäå]", 'g'), "a"); 38021 r = r.replace(new RegExp("æ", 'g'), "ae"); 38022 r = r.replace(new RegExp("ç", 'g'), "c"); 38023 r = r.replace(new RegExp("[èéêë]", 'g'), "e"); 38024 r = r.replace(new RegExp("[ìÃîï]", 'g'), "i"); 38025 r = r.replace(new RegExp("ñ", 'g'), "n"); 38026 r = r.replace(new RegExp("[òóôõö]", 'g'), "o"); 38027 r = r.replace(new RegExp("Å", 'g'), "oe"); 38028 r = r.replace(new RegExp("[ùúûü]", 'g'), "u"); 38029 r = r.replace(new RegExp("[ýÿ]", 'g'), "y"); 38030 38031 r = r.replace(new RegExp("[^\\w\\-@-]", 'g'), "-"); 38032 r = r.replace(new RegExp("--+", 'g'), "-"); 38033 38034 38035 if (r.lastIndexOf("-") > 0 && r.lastIndexOf("-") == r.length - 1) { 38036 r = r.substring(0, r.length - 1); 38037 } 38038 } 38039 38040 return r; 38041}; 38042 38043 38044CORE.GetQueryVariable = function (variable) { 38045 var query = window.location.search.substring(1); 38046 var vars = query.split("&"); 38047 for (var i = 0; i < vars.length; i++) { 38048 var pair = vars[i].split("="); 38049 if (pair[0] == variable) { return pair[1]; } 38050 } 38051 return (false); 38052} 38053 38054CORE.Post = function (url, data, callback, errorCallback, alwaysCallback) { 38055 return $.post(url, data, null, "json") 38056 .success(function (result) { 38057 if (callback) 38058 callback(result); 38059 }) 38060 .fail(function (err, status, errorMessage) { 38061 if (errorCallback != undefined && $.isFunction(errorCallback)) { 38062 errorCallback(err, status, errorMessage); 38063 } 38064 }) 38065 .always(function () { 38066 if (alwaysCallback != undefined && $.isFunction(alwaysCallback)) { 38067 alwaysCallback(); 38068 } 38069 }); 38070}; 38071 38072CORE.Get = function (url, data, callback, errorCallback, alwaysCallback) { 38073 return $.get(url, data, null, "json") 38074 .success(function (result) { 38075 if (callback) 38076 callback(result); 38077 }) 38078 .fail(function (err, status, errorMessage) { 38079 if (errorCallback != undefined && $.isFunction(errorCallback)) { 38080 errorCallback(err, status, errorMessage); 38081 } 38082 }) 38083 .always(function () { 38084 if (alwaysCallback != undefined && $.isFunction(alwaysCallback)) { 38085 alwaysCallback(); 38086 } 38087 }); 38088}; 38089 38090CORE.ValidateForm = function (formElem) { 38091 var $form; 38092 38093 $form = (formElem instanceof jQuery) ? formElem : $(formElem); 38094 38095 if (!$form.parsley().validate()) { 38096 return false; 38097 } 38098 38099 return true; 38100} 38101 38102; 38103/// <reference path="../_references.js" /> 38104var CORE = APP.Core, 38105 VM = APP.ViewModels, 38106 DATA = APP.Data; 38107 38108DATA.Sample = { 38109 GetSomething: function (callback) { 38110 var postData = { 38111 something: 'something' 38112 } 38113 APP.Core.Post('/some-url', postData, function () { 38114 //on success 38115 }, 38116 function () { 38117 //on error 38118 }, 38119 function () { 38120 //always do this... 38121 38122 if ($.isFunction(callback)) { 38123 callback(); 38124 } 38125 }); 38126 } 38127} 38128 38129DATA.Agility = { 38130 GetPage: function (pagePath) { 38131 38132 APP.clientPageRequest(pagePath); 38133 38134 } 38135} 38136 38137 38138 38139 38140; 38141var VM = APP.ViewModels; 38142 38143VM.RouterModel = function () { 38144 var self = this; 38145 38146 self.sammyApp = null; 38147 self.maxRedirectCount = 3; 38148 self.redirectCount = 0; 38149 self.languageCodeInPath = true; 38150 self.allLanguages = _serverContext.AllLanguages; 38151 self.currentLanguageCode = _serverContext.LanguageCode; 38152 self.initialLoad = true; 38153 self.forceUpdate = false; 38154 self.lastPath = ko.observable(null); 38155 self.modals = _serverContext.Modals; 38156 self.pages = _serverContext.Pages; 38157 38158 self.scheduledTimerID = ko.observable(0); 38159 38160 self.RouteNames = { 38161 //Checkout: { 38162 // Checkout: 'Checkout-Checkout', 38163 // Shipping: 'Checkout-Shipping',
38164 // Review: 'Checkout-Review', 38165 // Payment: 'Checkout-Payment', 38166 // Confirmation: 'Checkout-Confirmation' 38167 //}, 38168 //MyAccount: { 38169 // Manager: 'MyAccount-Manager', 38170 // Contact: 'MyAccount-Contact', 38171 // Billing: 'MyAccount-Billing', 38172 // Orders: 'MyAccount-Orders', 38173 // Security: 'MyAccount-Security' 38174 //} 38175 }; 38176}; 38177 38178/// 38179//proto 38180/// 38181ko.utils.extend(VM.RouterModel.prototype, { 38182 redirect: function (path) { 38183 var ROUTER = this; 38184 //ensure there isn't too many redirects accidentally 38185 if (ROUTER.redirectCount < ROUTER.maxRedirectCount) { 38186 ROUTER.redirectCount++; 38187 38188 ROUTER.sammyApp.setLocation(path); 38189 } 38190 }, 38191 setupRoutes: function () { 38192 38193 var ROUTER = this; 38194 38195 ROUTER.sammyApp = new Sammy(function() { 38196 38197 //////////////////////////////////////////////////////////////////////////////////////////////////////// 38198 /// BEFORE
38199 //////////////////////////////////////////////////////////////////////////////////////////////////////// 38200 38201 38202 //MATCH all get requests = /.*/ 38203 this.before(/.*/, 38204 function(context) { 38205 38206 if (ROUTER.forceUpdate) { 38207 ROUTER.forceUpdate = false; 38208 return; 38209 } 38210 38211 if (ROUTER.lastPath() != null) { 38212 38213 var incomingPath = context.path; 38214 var incomingParts = incomingPath.split('/'); 38215 var lastPath = ROUTER.lastPath.peek(); 38216 38217 /////////////////////////////////////////////////////////////////////////////////////////////////// 38218 /// KEEP LANGUAGE CODE IN PATH 38219 /////////////////////////////////////////////////////////////////////////////////////////////////// 38220 38221 //HACK: don't handle the language code because it messes up the "History" of the user and they can't press back... 38222 //if (ROUTER.languageCodeInPath) { 38223 // //ensure we keep the language code in the path at all times 38224 38225 // //look for /en-ca/{path} 38226 // var langCodePart = incomingParts[1]; 38227 38228 // if (langCodePart != ROUTER.currentLanguageCode) { 38229 // //there is no language code in the incoming path, add it and redirect! 38230 // var incomingPathWithLanguageCode = "/" + ROUTER.currentLanguageCode + incomingPath; 38231 // ROUTER.redirect(incomingPathWithLanguageCode); 38232 // return false; 38233 // } 38234 //} 38235
38236 //////////////////////////////////////////////////////////////////////////////////////////////////// 38237 /// KEEP PATH ON # ANCHOR 38238 /// if the incoming route is just a variation of a hash with the same path then don't reload the page 38239 //////////////////////////////////////////////////////////////////////////////////////////////////// 38240 38241 //let modals go through 38242 if (incomingPath.indexOf('#/m/') > -1) { 38243 return; 38244 } 38245 38246 var incomingPathNoHash = incomingPath; 38247 var lastPathNoHash = lastPath; 38248 38249 if (incomingPath.indexOf('#') > -1) { 38250 incomingPathNoHash = incomingPath.substr(0, incomingPath.indexOf('#')); 38251 } 38252 38253 if (lastPath.indexOf('#') > -1) { 38254 lastPathNoHash = lastPath.substr(0, lastPath.indexOf('#')); 38255 } 38256 38257 if (incomingPathNoHash == lastPathNoHash) { 38258 return false; 38259 } 38260 38261 } 38262 38263 }); 38264
38265 ////////////////////////////////////////////////////////////////////////////////////////////////////// 38266 /// HANDLE ROUTES 38267 ////////////////////////////////////////////////////////////////////////////////////////////////////// 38268 38269 //MODALS 38270 // -- Offers 38271 //this.get(ROUTER.modals.OfferDetailsPath + ':code', function (context) { 38272 38273 // if (context.params.code) { 38274 // ROUTER.getModal.Offer(context.params.code); 38275 // } 38276 38277 //}); 38278 38279 //CATCH ALL 38280 this.get(/.*/, 38281 function(context) { 38282 38283 if (!ROUTER.initialLoad) { 38284 38285 ROUTER.getPage(context.path); 38286 } 38287 38288 //reset the redirect count 38289 ROUTER.redirectCount = 0; 38290 38291 }); 38292 38293 // Override this function so that Sammy doesn't mess with forms 38294 this._checkFormSubmission = function(form) { 38295 return true; 38296 }; 38297 38298 //404 38299 this.notFound = function(verb, path) { 38300 //route not matched 38301 } 38302 38303 //Run after every update 38304 this.after(function() { 38305 ROUTER.routeChanged(); 38306 APP.closeAllGlobalElements(); 38307 APP.mobileMenu.open(false); 38308 }); 38309 }); 38310 38311 ROUTER.sammyApp.debug = false; 38312 38313 ROUTER.sammyApp.run(); 38314 38315 }, 38316 routeChanged: function () { 38317 var ROUTER = this; 38318 ROUTER.initialLoad = false; 38319 var path = location.pathname + location.search; 38320 ROUTER.lastPath(path); 38321 }, 38322 addRoute: function (routeName, regexPath, callback) { 38323 var ROUTER = this; 38324 var existingRoutes = ROUTER.sammyApp.routes.get; 38325 var routeExists = false; 38326 38327 for (var i in existingRoutes) { 38328 var route = existingRoutes[i]; 38329 if (route.name && route.name == routeName) { 38330 routeExists = true; 38331 } 38332 } 38333 38334 if (!routeExists) { 38335 //add the route 38336 ROUTER.sammyApp.get(regexPath, function (context) { 38337 ROUTER.lastPath(context.path); 38338 callback(context); 38339 ROUTER.routeChanged(); 38340 }); 38341 //move it to the top of the list 38342 ROUTER.sammyApp.routes.get.unshift(ROUTER.sammyApp.routes.get.pop()) 38343 //set the custom route name/id 38344 ROUTER.sammyApp.routes.get[0].name = routeName; 38345 } 38346 }, 38347 removeRoute: function (routeName) { 38348 var ROUTER = this; 38349 var existingRoutes = ROUTER.sammyApp.routes.get; 38350 var routeExistsIndex = -1; 38351 38352 for (var i in existingRoutes) { 38353 var route = existingRoutes[i]; 38354 if (route.name && route.name == routeName) { 38355 routeExistsIndex = i; 38356 } 38357 } 38358 38359 if (routeExistsIndex > -1) { 38360 //remove the route 38361 ROUTER.sammyApp.routes.get.splice(routeExistsIndex, 1); 38362 } 38363 }, 38364 reRun: function () { 38365 var ROUTER = this; 38366 //need to re-evaluate the routes now that we've added them 38367 ROUTER.forceUpdate = true; 38368 ROUTER.sammyApp.runRoute('get', location.pathname + location.search); 38369 }, 38370 getPage: function (path) { 38371 38372 var ROUTER = this; 38373 38374 if (ROUTER.scheduledTimerID() > 0) { 38375 window.clearTimeout(ROUTER.scheduledTimerID()); 38376 } 38377 38378 APP.Data.Agility.GetPage(path); 38379 }, 38380 getPageTimeout: function (path, timeout) { 38381 38382 var ROUTER = this; 38383 38384 var timerID = window.setTimeout(function () { 38385 38386 APP.Data.Agility.GetPage(path); 38387 38388 }, timeout); 38389 38390 ROUTER.scheduledTimerID(timerID); 38391 }, 38392 getModal: { 38393 //Offer: function (code) { 38394 // var req = new DATA.CMSAPI.Offers.Details(); 38395 // req.args.LanguageCode = _serverContext.LanguageCode; 38396 // req.args.Code = code; 38397 38398 // req.onSuccess = function (res) { 38399 // if (res.Offer) { 38400 // var modal = new App.ViewModels.Modal('offer-details', code, 'offer-details-modal-tmpl') 38401 // modal.viewModelForTemplate = new App.ViewModels.OfferDetailsModel(res.Offer); 38402 // modal.open(); 38403 // } 38404 // } 38405 38406 // req.execute(); 38407 38408 //}, 38409 //MyCard: function () { 38410 // var modal = new App.ViewModels.Modal('my-card', 'my-card', 'my-card-tmpl').open(); 38411 //} 38412 }, 38413 navigateHome: function () { 38414 var ROUTER = this; 38415 ROUTER.navigate('/'); 38416 }, 38417 //redirectToLogin: function () { 38418 // var ROUTER = this; 38419 // var qs = [ 38420 // { key: APP.Core.Keys.ReturnUrl, value: window.location.pathname } 38421 // ]; 38422 38423 // ROUTER.navigate(ROUTER.pages.Login, qs); 38424 //}, 38425 38426 //redirectToLogout: function () { 38427 // var ROUTER = this; 38428 // var qs = [ 38429 // { key: APP.Core.Keys.ReturnUrl, value: window.location.pathname } 38430 // ]; 38431 38432 // ROUTER.navigate(ROUTER.pages.Logout, qs); 38433 //}, 38434 navigate: function (url, params) { 38435 var ROUTER = this; 38436 38437 //params: [ { key: 'k', value: 'v } ] 38438 if (params) { 38439 for (var i in params) { 38440 if (i == 0) { 38441 url += "?"; 38442 } else { 38443 url += "&"; 38444 } 38445 url += params[i].key; 38446 url += "="; 38447 url += params[i].value; 38448 } 38449 } 38450 38451 38452 //absolute 38453 if (url.indexOf('http') > -1) { 38454 window.location.href = url; 38455 } else { 38456 //relative
38457 ROUTER.sammyApp.setLocation(url); 38458 } 38459 }, 38460 afterPageLoaded: function () { 38461 //do something after the next page has loaded 38462 } 38463}); 38464 38465; 38466/// <reference path="../_references.js" /> 38467 38468//toggleable observable 38469ko.observable.fn.toggleable = function () { 38470 var self = this; 38471 self.toggle = function () { 38472 self(!self()); 38473 }; 38474 38475 return self; 38476};; 38477if (typeof (window.Agility) == "undefined") { 38478 window.Agility = new Object(); 38479} 38480 38481if (typeof (window.Agility.Search) == "undefined") { 38482 window.Agility.Search = new Object(); 38483} 38484 38485(function (S, $) { 38486 38487 ///GLOBAL VARIABLES - set in the init 38488 S.SearchUrl = null; 38489 S.WebsiteName = null; 38490 S.AuthKey = null; 38491 S.LanguageCode = null; 38492 38493 38494 _postCORS = function (url, data) { 38495 38496 url = S.SearchUrl + url; 38497 38498 var authHeaders = {}; 38499 authHeaders["as-WebsiteName"] = S.WebsiteName; 38500 authHeaders["as-AuthKey"] = S.AuthKey; 38501 38502 return $.ajax(url, { 38503 type: "POST", 38504 data: data, 38505 dataType: "json", 38506 headers: authHeaders, 38507 xhrFields: { 38508 withCredentials: true 38509 }, 38510 crossDomain: true 38511 }); 38512 }; 38513 38514 38515 /** 38516 * A Config object to initialize the Search API. 38517 * @typedef {object} APIConfig 38518 * @property {String} url the search service url 38519 * @property {String} websiteName the website name 38520 * @property {String} authKey the authorization key 38521 * @property {String} lang the default language code 38522 */ 38523 /** 38524 * Initialize the Agility Search API. 38525 * @param {APIConfig} config The API Config object. 38526 */ 38527 S.Init = function (config) { 38528 S.SearchUrl = config.url; 38529 S.WebsiteName = config.websiteName; 38530 S.AuthKey = config.authKey; 38531 S.LanguageCode = config.lang; 38532 38533 38534 try { 38535 //try to get the current language code if one wasn't provided 38536 if (!S.LanguageCode || S.LanguageCode == "") { 38537 var attr = $('meta[name=agility_attributes]').attr("content"); 38538 38539 if (attr && attr != "") { 38540 var ary = attr.split(", "); 38541 for (var i = 0; i < ary.length; i++) { 38542 if (ary[i].indexOf("Language=") != -1) { 38543 var languageCode = ary[i].substring("Language=".length); 38544 S.LanguageCode = languageCode; 38545 } 38546 } 38547 } 38548 38549 } 38550 } catch (err) { } 38551 38552 var builtIn = new S.BuiltInSearch(); 38553 var builtInGrouped = new S.BuiltInGroupedSearch(); 38554 38555 $(function () { 38556 38557 //TODO: when we release Personalization, make this work with the personalization event 38558 builtIn.Init(); 38559 builtInGrouped.Init(); 38560 }); 38561 }; 38562 38563 38564 /** 38565 * A Search Query object 38566 * @typedef {object} Query 38567 * @property {String} query 38568 * @property {String} languageCode (optional) 38569 * @property {String} category (optional) 38570 * @property {String} domain (optional) 38571 * @property {Number} top (optional) 38572 * @property {Number} skip (option) 38573 */ 38574 /** 38575 * Execute a Search query 38576 * @param {Query} arg The search query object. 38577 * @returns a deferred object 38578 */ 38579 S.Query = function (arg) { 38580 if (arg == undefined 38581 || arg == null) { 38582 return; 38583 } 38584 38585 var url = "/search"; 38586 38587 if (arg.languageCode === undefined) { 38588 arg.languageCode = S.LanguageCode; 38589 } 38590 38591 return _postCORS(url, arg); 38592 }; 38593 38594 /** 38595 * A Grouped Query object 38596 * @typedef {object} GroupedQuery 38597 * @property {String} query 38598 * @property {String} languageCode (optional) 38599 * @property {String} domain (optional) 38600 * @property {Number} top (optional) - Max number of returned items in each category 38601 */ 38602 /** 38603 * Execute a Grouped Search query 38604 * @param {GroupedQuery} arg The group search query object. 38605 * @returns a deferred object 38606 */ 38607 S.GroupedQuery = function (arg) { 38608 if (arg == undefined 38609 || arg == null) { 38610 return; 38611 } 38612 38613 var url = "/GroupedQuery"; 38614 38615 if (arg.languageCode === undefined) { 38616 arg.languageCode = S.LanguageCode; 38617 } 38618 38619 return _postCORS(url, arg); 38620 }; 38621 38622 38623 /** 38624 * An AutoComplete object 38625 * @typedef {object} AutoComplete 38626 * @property {String} query 38627 * @property {String} languageCode (optional) 38628 * @property {String} category (optional) 38629 * @property {Number} top (optional) 38630 * @property {Boolean} fuzzy (option) 38631 */ 38632 /** 38633 * Execute an Autocomplete query 38634 * @param {AutoComplete} arg The search query object. 38635 * @returns a deferred object 38636 */ 38637 S.AutoComplete = function (arg) { 38638 if (arg == undefined 38639 || arg == null) { 38640 return; 38641 } 38642 38643 var url = "/autocomplete"; 38644 38645 if (!arg.languageCode) { 38646 arg.languageCode = S.LanguageCode; 38647 } 38648 38649 return _postCORS(url, arg); 38650 }; 38651 38652 /** 38653 * A Conversion object 38654 * @typedef {object} Conversion 38655 * @property {String} url 38656 */ 38657 /** 38658 * Record a conversion 38659 * @param {Conversion} arg The conversion object 38660 * @returns a deferred object 38661 */ 38662 S.Conversion = function (arg) { 38663 if (arg == undefined 38664 || arg == null) { 38665 return; 38666 } 38667 38668 var url = "/conversion"; 38669 38670 return _postCORS(url, arg); 38671 }; 38672 38673 var _injectStyle = function () { 38674 38675 var cssUrl = S.SearchUrl + "/Content/Public.min.css"; 38676 var autoCompleteUrl = S.SearchUrl + "/scripts/jquery.auto-complete.min.js"; 38677 38678 $("<link/>", { 38679 rel: "stylesheet", 38680 type: "text/css", 38681 href: cssUrl 38682 }).appendTo("head"); 38683 38684 38685 _scriptLoader = $.getScript(autoCompleteUrl); 38686 38687 }; 38688 38689 38690 38691 S.BuiltInGroupedSearch = function () { 38692 38693 var self = this; 38694 38695 self.Init = function () { 38696 //_injectStyle(); 38697 $(".agility-grouped-search-panel").each(function () { 38698 _createGroupedSearchField(this); 38699 }); 38700 }; 38701 38702 _scriptLoader = null; 38703 38704 var _ajaxRequestQuery = null; 38705 var skip = 0; 38706 38707 _createGroupedSearchField = function (elem) { 38708 38709 var $elem = $(elem); 38710 38711 var top = $elem.data('top') || 5; 38712 var redirectPath = $elem.data('redirect-path');
38713 var delay = $elem.data('delay') || 500; 38714 var groupCount = $elem.data('group-count') || 0; 38715 var isPopOver = $elem.data('pop-over') == null || $elem.data('pop-over') == true; 38716 38717 var html = "<form action='' method='post' class='agility-grouped-search-form'><input type='search' placeholder='Search' /><button type='submit'>Search</button>"; 38718 html += '<div class="agility-grouped-search-results hidden-panel"><div class="agility-grouped-search-results-inner"></div></div></form>'; 38719 38720 $(html).appendTo($elem); 38721 38722 var searchForm = $(".agility-grouped-search-form", $elem); 38723 var searchField = $("input", searchForm); 38724 var resultsPanel = $(".agility-grouped-search-results-inner", $elem); 38725 var resultsPanelOuter = $('.agility-grouped-search-results', $elem); 38726 38727 if (isPopOver) { 38728 resultsPanelOuter.addClass('popOver'); 38729 38730 $(document).mouseup(function (e) { 38731 var container = resultsPanelOuter; 38732 38733 // if the target of the click isn't the container nor a descendant of the container 38734 if (!container.is(e.target) && container.has(e.target).length === 0) { 38735 var lists = $('ul', container); 38736 38737 if (lists && lists.length > 0) { 38738 container.addClass('hidden-panel'); 38739 } 38740 } 38741 }); 38742 } else { 38743 resultsPanelOuter.addClass('inline'); 38744 } 38745 38746 var scriptLoaded = function () { 38747 var wto; 38748 38749 $('.agility-grouped-search-form input', $elem).on('input', function (e) { 38750 if (_ajaxRequestQuery) _ajaxRequestQuery.abort(); 38751 38752 var term = $(this).val(); 38753 38754 if (term.length >= 3) { 38755 _clearTimeoutAndStartLoading(wto, resultsPanel, true); 38756 38757 wto = setTimeout(function () { 38758 38759 term = term.toLowerCase(); 38760 38761 38762 _ajaxRequestQuery = S.GroupedQuery({ 38763 query: term, 38764 top: top, 38765 groupCount: groupCount 38766 }).done(function (res) { 38767 if (!res.IsError) { 38768 _renderGroupedResults(res.ResponseData, resultsPanel); 38769 38770 if (res.Count > 0) { 38771 hasResults = true; 38772 } else { 38773 hasResults = false; 38774 } 38775 } 38776 }).always(function () { 38777 resultsPanel.removeClass('loading'); 38778 }); 38779 }, delay); 38780 } else { 38781 _clearTimeoutAndStartLoading(wto, resultsPanel, false); 38782 } 38783 }); 38784 38785 $('.agility-grouped-search-form input', $elem).keydown(function (event) { 38786 if (event.keyCode === 40) { 38787 //down arrow key 38788 var firstGroup = $('.agility-grouped-result', resultsPanel).first(); 38789 38790 if (firstGroup) { 38791 var firstResult = $('ul li', firstGroup).first(); 38792 38793 firstResult.addClass('selected'); 38794 38795 firstResult.focus(); 38796 38797 return false; 38798 } 38799 } else if (event.keyCode === 38) { 38800 //up arrow key 38801 var lastGroup = $('.agility-grouped-result', resultsPanel).last(); 38802 38803 if (lastGroup) { 38804 var lastResult = $('ul li', lastGroup).last(
38804); 38805 38806 lastResult.addClass('selected'); 38807 38808 lastResult.focus(); 38809 38810 return false; 38811 } 38812 } else { 38813 return true; 38814 } 38815 }); 38816 }; 38817 38818 38819 var _clearTimeoutAndStartLoading = function (wto, resultsPanel, startLoading) { 38820 clearTimeout(wto); 38821 38822 resultsPanel.empty(); 38823 resultsPanel.parent().removeClass('hidden-panel'); 38824 38825 if (startLoading) { 38826 resultsPanel.addClass('loading'); 38827 } else { 38828 resultsPanel.removeClass('loading'); 38829 } 38830 }; 38831 38832 var _renderGroupedResults = function (response, resultsPanel) { 38833 for (var i = 0; i < response.GroupedResults.length; i++) { 38834 resultsPanel.append(_getGroupHTML(response.GroupedResults[i])); 38835 } 38836 38837 $('ul li', resultsPanel).keydown(function () { 38838 if (event.keyCode === 40) { 38839 //down arrow key 38840 var nextResult = $(this).next(); 38841 38842 if (nextResult && nextResult.length != 0) { 38843 $(this).removeClass('selected'); 38844 nextResult.addClass('selected'); 38845 nextResult.focus(); 38846 38847 } else { 38848 //go to the next group 38849 var nextGroup = $(this).parent().parent().next(); 38850 38851 if (nextGroup && nextGroup.length != 0) { 38852 var firstResultOfNextGroup = $('li', nextGroup).first(); 38853 38854 //result in next group 38855 $(this).removeClass('selected'); 38856 firstResultOfNextGroup.addClass('selected'); 38857 firstResultOfNextGroup.focus(); 38858 } else { 38859 //go back to input 38860 $(this).removeClass('selected'); 38861 searchField.focus(); 38862 } 38863 38864 } 38865 38866 return false; 38867 } else if (event.keyCode === 38) { 38868 //up arrow key 38869 var previousResult = $(this).prev(); 38870 38871 if (previousResult && previousResult.length != 0) { 38872 $(this).removeClass('selected'); 38873 previousResult.addClass('selected');
38874 previousResult.focus(); 38875 38876 } else { 38877 //go to the previous group 38878 var previousGroup = $(this).parent().parent().prev(); 38879 38880 if (previousGroup && previousGroup.length != 0) { 38881 var lastResultOfPreviousGroup = $('li', previousGroup).last(); 38882 38883 //result in next group 38884 $(this).removeClass('selected'); 38885 lastResultOfPreviousGroup.addClass('selected'); 38886 lastResultOfPreviousGroup.focus(); 38887 } else { 38888 //go back to input 38889 $(this).removeClass('selected'); 38890 searchField.focus(); 38891 } 38892 } 38893 38894 return false; 38895 } else if (event.keyCode === 13) { 38896 window.location.href = $('a', $(this)).attr('href'); 38897 38898 return false; 38899 } else { 38900 return true; 38901 } 38902 }); 38903 }; 38904 38905 var _getGroupHTML = function (group) { 38906 var html = '<div class="agility-grouped-result">'; 38907 html += '<h3 class="agility-grouped-result-name">'; 38908 html += group.Name; 38909 html += '</h3>'; 38910 38911 html += '<ul class="agility-grouped-search-list">'; 38912 38913 var flags = [], output = [], l = group.Results.length, i; 38914 for (i = 0; i < l; i++) { 38915 if (flags[group.Results[i].Title]) continue; 38916 flags[group.Results[i].Title] = true; 38917 output.push(group.Results[i]); 38918 } 38919 38920 for (var i = 0; i < output.length; i++) { 38921 var result = output[i]; 38922 38923 html += '<li tabindex="-1">'; 38924 38925 html += '<a href="' + result.Url + '" target="_self">'; 38926 html += result.Title; 38927 html += '</a>'; 38928 38929 html += '</li>'; 38930 } 38931 38932 html += '</ul>'; 38933 html += '</div>'; 38934 38935 return html; 38936 }; 38937 38938 _scriptLoader.done(scriptLoaded.bind(searchField)); 38939 38940 searchForm.submit(function (event) { 38941 //redirect to search url 38942 event.preventDefault(); 38943 38944 window.location.href = redirectPath + '?q=' + searchField.val(); 38945 38946 return false; 38947 }); 38948 }; 38949 }; 38950 38951 S.BuiltInSearch = function () { 38952 38953 var self = this; 38954 38955 self.Init = function () { 38956 _injectStyle(); 38957 38958 $(".agility-search-panel").each(function () { 38959 _createSearchField(this); 38960 }); 38961 }; 38962 38963 _scriptLoader = null; 38964 38965 var ajaxRequestAutoComplete = null; 38966 var _ajaxRequestQuery = null; 38967 var skip = 0; 38968 38969 _createSearchField = function (elem) { 38970 38971 var $elem = $(elem); 38972 38973 var currentQuery = S.GetQueryString("q"); 38974 var currentSkip = parseInt(S.GetQueryString("s")); 38975 38976 var html = "<form action='' method='post' class='agility-search-form'><input type='search' placeholder='Search' /><button type='submit'>Search</button></form>"; 38977 html += "<div class='agility-search-results'></div>"; 38978 38979 $(html).appendTo($elem); 38980 38981 var searchForm = $(".agility-search-form", $elem); 38982 var searchField = $("input", searchForm); 38983 var resultsPanel = $(".agility-search-results", $elem); 38984 38985 searchField.val(currentQuery); 38986 38987 var scriptLoaded = function () { 38988 38989 $(this).autoComplete({ 38990 minChars: 3, 38991 source: function (term, response) { 38992 38993 try { 38994 if (ajaxRequestAutoComplete) ajaxRequestAutoComplete.abort(); 38995 } catch (e) { } 38996 38997 term = term.toLowerCase(); 38998 38999 39000 var timeout = setTimeout(function () { 39001 response(["Loading..."]); 39002 }, 250); 39003 39004 ajaxRequestAutoComplete = S.AutoComplete({ 39005 query: term 39006 }).done(function (res) { 39007 if (!res.IsError) { 39008 response(res.ResponseData); 39009 } 39010 }).always(function () { 39011 clearTimeout(timeout); 39012 }); 39013 39014 }, 39015 onSelect: function (e, term, item) { 39016 if (e.type == "mousedown") { 39017 searchForm.submit(); 39018 } 39019 } 39020 }); 39021 }; 39022 _scriptLoader.done(scriptLoaded.bind(searchField)); 39023 39024 searchForm.submit(function (event) { 39025 39026 event.preventDefault(); 39027 39028 var query = $.trim(searchField.val()); 39029 skip = 0; 39030 if (query.length > 2) { 39031 S.SetQueryString("q", query); 39032 S.SetQueryString("s", null); 39033 39034 _performSearch(query, resultsPanel); 39035 39036 searchField.blur(); 39037 setTimeout(function () { 39038 searchField.focus(); 39039 }, 50); 39040 39041 39042 } 39043 39044 return false; 39045 }); 39046 39047 if (currentQuery && currentQuery.length > 2) { 39048 39049 if (currentSkip > 0) skip = currentSkip; 39050 _performSearch(currentQuery, resultsPanel); 39051 } 39052 39053 }; 39054 39055 39056 var _performSearch = function (query, resultsPanel) { 39057 39058 if (_ajaxRequestQuery != null) { 39059 _ajaxRequestQuery.abort(); 39060 } 39061 39062 var panelHeight = resultsPanel.height(); 39063 resultsPanel.css("minHeight", panelHeight + "px"); 39064 39065 var timeout = setTimeout(function () { 39066 resultsPanel.html("<div class='agility-search-loader'>Loading...</div>"); 39067 }, 300); 39068 39069 39070 _ajaxRequestQuery = S.Query({ 39071 query: query, 39072 top: 10, 39073 skip: skip, 39074 }).done(function (res) { 39075 _renderResults(res, resultsPanel); 39076 39077 }).fail(function (err) { 39078 _renderResults({ IsError: true, ErrorMessage: err }, resultsPanel); 39079 39080 }).always(function () { 39081 clearTimeout(timeout); 39082 resultsPanel.css("min-height", ""); 39083 });; 39084 39085 }; 39086 39087 _renderResults = function (res, resultsPanel) { 39088 39089 var html = "<div class='agility-results-header'></div>"; 39090 html += "<div class='agility-results-listing'></div>"; 39091 html += "<div class='agility-results-pager'></div>"; 39092 39093 resultsPanel.html(html); 39094 var header = $(".agility-results-header", resultsPanel); 39095 var listing = $(".agility-results-listing", resultsPanel); 39096 39097 var pagers = $(".agility-results-pager", resultsPanel); 39098 39099 if (res.IsError) { 39100 header.text("An error occurred."); 39101 39102 if (console) console.warn(res.ErrorMessage); 39103 return; 39104 } 39105 39106 var result = res.ResponseData; 39107 if (!result) { 39108 header.text("No results."); 39109 } else if (result.Count == 0 || !result.Results) { 39110 header.text("No results for " + result.Query); 39111 } else { 39112 header.text("Showing result " + result.FromNumber + " to " + result.ToNumber + " of " + result.Count + " for " + result.Query); 39113 39114 var itemHtml = "<div class='agility-result-item'>" 39115 itemHtml += "<a class='agility-result-title'></a>" 39116 itemHtml += "<div class='agility-result-link'></div>" 39117 itemHtml += "<div class='agility-result-description'></div>" 39118 itemHtml += "</div>" 39119 39120 for (var i = 0; i < result.Results.length; i++) { 39121 39122 var item = result.Results[i];
39123 39124 var itemObj = $(itemHtml); 39125 itemObj.appendTo(listing); 39126 39127 var itemTitle = $(".agility-result-title", itemObj); 39128 var itemLink = $(".agility-result-link", itemObj); 39129 var itemDesc = $(".agility-result-description", itemObj); 39130 39131 if (item.Category) { 39132 $("<div class='agility-result-category'></div>").prependTo(itemObj); 39133 var itemCat = $(".agility-result-category", itemObj); 39134 itemCat.text(item.Category); 39135 } 39136 39137 39138 if (item.ImageUrl) { 39139 $("<div class='agility-result-image'></div>").prependTo(itemObj); 39140 var itemImage = $(".agility-result-image", itemObj); 39141 itemImage.css("background-image", "url('" + item.ImageUrl + "')"); 39142 } 39143 39144 39145 39146 itemTitle.text(item.Title).attr("href", item.Url); 39147 itemLink.text(item.Url); 39148 39149 itemDesc.html(item.Highlight); 39150 39151 } 39152 39153 var pHtml = ""; 39154 39155 if (result.FromNumber > 1) { 39156 pHtml += "<a class='prev-link' href='#'>Previous</a>"; 39157 } 39158 39159 if (result.ToNumber < result.Count) { 39160 if (pHtml != "") { 39161 pHtml += " | " 39162 } 39163 pHtml += "<a class='next-link' href='#'>Next</a>"; 39164 } 39165 39166 39167 39168 if (pHtml != "") { 39169 pagers.html(pHtml); 39170 pagers.css("display", "block"); 39171 } 39172 39173 $(".agility-result-title", resultsPanel).click(function () { 39174 39175 var url = $(this).attr("href"); 39176 S.Conversion({ url: url }); 39177 }); 39178 $(".next-link", pagers).click(function () { 39179 skip = result.ToNumber; 39180 S.SetQueryString("s", skip); 39181 //_performSearch(result.Query, resultsPanel); 39182 39183 return false; 39184 }); 39185 39186 $(".prev-link", pagers).click(function () { 39187 var pageSize = result.ToNumber - result.FromNumber + 1; 39188 skip = result.FromNumber - pageSize - 1; 39189 if (skip < 0) skip = 0; 39190 S.SetQueryString("s", skip); 39191 //_performSearch(result.Query, resultsPanel); 39192 39193 return false; 39194 39195 }); 39196 39197 39198 39199 } 39200 39201 39202 39203 39204 }; 39205 }; 39206 39207 S.SetQueryString = function (name, value, url) { 39208 if (url == undefined || url == null || url == "") { 39209 url = location.href; 39210 } 39211 39212 if (url.indexOf("#") != -1) { 39213 url = url.substring(0, url.indexOf("#")); 39214 } 39215 39216 var queryObj = {}; 39217 39218 var urlNoQuery = url; 39219 39220 var index = url.indexOf("?"); 39221 if (index > 1) { 39222 39223 urlNoQuery = url.substring(0, index); 39224 39225 //get the current query strings... 39226 var qstr = url.substring(index + 1, url.length); 39227 var ary1 = qstr.split("&"); 39228 39229 for (var i = 0; i < ary1.length; i++) { 39230 var q = ary1[i]; 39231 var ary2 = q.split("="); 39232 if (ary2.length == 2) { 39233 var qName = decodeURIComponent(ary2[0]); 39234 39235 var qValue = ary2[1]; 39236 qValue = qValue.replace(/\+/g, "%20"); 39237 qValue = decodeURIComponent(qValue); 39238 39239 39240 queryObj[qName] = qValue; 39241 } 39242 } 39243 } 39244 39245 if (value) { 39246 queryObj[name] = value; 39247 } else { 39248 delete queryObj[name]; 39249 } 39250 39251 39252 39253 var newUrl = ""; 39254 for (var qn in queryObj) { 39255 var qv = queryObj[qn]; 39256 39257 if (newUrl == "") { 39258 newUrl += "?"; 39259 } else { 39260 newUrl += "&"; 39261 } 39262 newUrl += encodeURIComponent(qn) + "=" + encodeURIComponent(qv); 39263 } 39264 39265 //push this to the address bar... 39266 newUrl = urlNoQuery + newUrl; 39267 39268 history.pushState({}, document.title, newUrl); 39269 39270 } 39271 39272 S.GetQueryString = function (name, url) { 39273 /// <summary> 39274 /// Gets a variable from the query string. 39275 /// </summary> 39276 /// <param name="name" type="String">QueryString variable to retrieve.</param> 39277 /// <param name="url" type="String">(Optional) the url to take the querystring from. If this is not present, the current url is used.</param> 39278 39279 if (url == undefined || url == null || url == "") { 39280 url = location.href; 39281 } 39282 39283 //strip off the hash 39284 if (url.indexOf("#") != -1) { 39285 url = url.substring(0, url.indexOf("#")); 39286 } 39287 39288 var index = url.indexOf("?"); 39289 if (index < 1) return null; 39290 39291 var qstr = url.substring(index + 1, url.length); 39292 39293 var ary1 = qstr.split("&"); 39294 var retValue = null; 39295 39296 for (var i = 0; i < ary1.length; i++) { 39297 var q = ary1[i]; 39298 var ary2 = q.split("="); 39299 if (ary2.length == 2) { 39300 if (decodeURIComponent(ary2[0]).toLowerCase() == name.toLowerCase()) { 39301 var retValue = ary2[1];
39302 retValue = retValue.replace(/\+/g, "%20"); 39303 return decodeURIComponent(retValue); 39304 } 39305 } 39306 } 39307 39308 return null; 39309 39310 } 39311 39312 39313 39314 39315 39316 39317 39318})(Agility.Search, jQuery);; 39319/// <reference path="../_references.js" /> 39320 39321ko.bindingHandlers.articleGallery = { 39322 init: function (element, valueAccessor, allBindings, viewModel) { 39323 $('.news-details__gallery-main').slick({ 39324 slidesToShow: 1, 39325 slidesToScroll: 1, 39326 arrows: false, 39327 fade: true, 39328 asNavFor: '.news-details__gallery-nav' 39329 }); 39330 39331 $('.news-details__gallery-nav').slick({ 39332 slidesToShow: 2, 39333 slidesToScroll: 1, 39334 asNavFor: '.news-details__gallery-main', 39335 centerMode: true, 39336 focusOnSelect: true 39337 }); 39338 } 39339}; 39340; 39341/// <reference path="../../_references.js" /> 39342 39343// Found on https://stackoverflow.com/questions/20817710/knockout-custom-html-binding 39344 39345ko.bindingHandlers.bindHTML = { 39346 init: function () { 39347 return { 'controlsDescendantBindings': true }; 39348 }, 39349 update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 39350 // setHtml will unwrap the value if needed 39351 ko.utils.setHtml(element, valueAccessor()); 39352 39353 var elementsToAdd = element.children; 39354 39355 for (var i = 0; i < elementsToAdd.length; i++) { 39356 ko.cleanNode(elementsToAdd[i]); //Clean node from Knockout bindings 39357 ko.applyBindings(bindingContext, elementsToAdd[i]); 39358 } 39359 } 39360};; 39361/// <reference path="../../_references.js" /> 39362 39363ko.bindingHandlers.clientFrameLoader = { 39364 update: function (element, valueAccessor, allBindings, viewModel) { 39365 39366 //function that runs when any dependency in the valueAccessor changes 39367 var clientPageRequest = ko.unwrap(valueAccessor()); 39368 var $frame = $(element); 39369 39370 var getHash = function (url) { 39371 var tag = document.createElement("a"); 39372 39373 var hash = ""; 39374 39375 tag.href = url; 39376 39377 if (!!tag.hash && tag.hash.length > 1) { 39378 hash = tag.hash.substring(1); 39379 } 39380 39381 return hash; 39382 }; 39383 39384 var getUrl = function (url) { 39385 var tag = document.createElement("a"); 39386 39387 var href = ""; 39388 39389 tag.href = url; 39390 39391 if (!!tag.pathname) { 39392 href = tag.pathname + tag.search; 39393 } 39394 39395 return href; 39396 }; 39397 39398 if (clientPageRequest != null) { 39399 39400 $frame.attr('src', APP.Core.Keys.AgilityPageAPIBasePath + encodeURIComponent(getUrl(clientPageRequest))); 39401 $frame.on('load', function (data) { 39402 39403 var contentsText = $(this).contents().find('body').text(); 39404 var resultJSON = $.parseJSON(contentsText); 39405 39406 if (resultJSON.isError) { 39407 //got a problem? hard redirect... 39408 window.location.href = clientPageRequest; 39409 } else if (resultJSON.redirect_location != null) { 39410 //this is a redirect 39411 APP.Router.sammyApp.setLocation(resultJSON.redirect_location); 39412 } 39413 else { 39414 39415 //set a unique ID 39416 resultJSON.page.id = APP.newPageID(); 39417 39418 // set the hash, if we have one 39419 resultJSON.page.hash = getHash(clientPageRequest); 39420 39421 //set the new page 39422 APP.page(resultJSON.page); 39423 39424 //remove the load event - won't need it again 39425 $frame.unbind('load'); 39426 39427 //clear the frame - this so that the frame doesn't remain the same in the dom and doesn't mess with the back/forward browser behaviour 39428 APP.clientPageRequest(null); 39429 39430 //Reattach search: 39431 Agility.Search.Init({ url: "https://search.agilitycms.com", websiteName: "EMSB", lang: "", authKey: "9fLju8eeNyfB1i5ZjB7drTfY7UEIu6y8V4lGbTF7K60" });
39432 39433 } 39434 39435 39436 39437 }); 39438 39439 39440 } 39441 39442 39443 } 39444}; 39445; 39446/// <reference path="../_references.js" /> 39447 39448ko.bindingHandlers.documentList = { 39449 init: function (element, valueAccessor, allBindings, viewModel) { 39450 $(element).click(function () { 39451 $(element).toggleClass('open'); 39452 $(element).children().first().next().slideToggle(); 39453 }) 39454 39455 } 39456}; 39457; 39458/// <reference path="../_references.js" /> 39459 39460ko.bindingHandlers.dropdownMenu = { 39461 39462 init: function (element, valueAccessor, allBindings, viewModel) { 39463 var options = valueAccessor() || [], 39464 linkClass = options.linkClass || "", 39465 activeClass = options.activeClass || linkClass + "--open", 39466 dropdownClass = options.dropdownClass || linkClass + "__dropdown", 39467 dropdownActiveClass = options.dropdownActiveClass || dropdownClass + "--open"; 39468 39469 if (linkClass != "") { 39470 var links = document.getElementsByClassName(linkClass); 39471 console.log(links); 39472 39473 for (i = 0; i < links.length; i++) { 39474 links[i].addEventListener('focus', function (e) { 39475 }, true); 39476 39477 links[i].addEventListener('blur', function (e) { 39478 let self = this; 39479 }, true); 39480 39481 } 39482 } 39483 } 39484}; 39485; 39486/// <reference path="../_references.js" /> 39487 39488ko.bindingHandlers.employmentExpand = { 39489 init: function (element, valueAccessor, allBindings, viewModel) { 39490 //function runs when element is added to the DOM 39491 $(element).click(function () { 39492 console.log(this) 39493 var elParent = $(this).parent(); 39494 console.log(elParent); 39495 var grandParent = elParent.parent(); 39496 console.log(grandParent) 39497 var target = grandParent.children(); 39498 console.log(target); 39499 target.toggleClass('open'); 39500 }) 39501 $(element).keydown(function (e) { 39502 if (e.which === 13) { 39503 var elParent = $(this).parent(); 39504 console.log(elParent); 39505 var grandParent = elParent.parent(); 39506 console.log(grandParent) 39507 var target = grandParent.children(); 39508 console.log(target); 39509 target.toggleClass('open'); 39510 } 39511 39512 }) 39513 }, 39514}; 39515; 39516ko.bindingHandlers.globalLoading = { 39517 update: function (element, valueAccessor, allBindings, viewModel) { 39518 //function that runs when any dependency in the valueAccessor changes 39519 var isLoading = ko.unwrap(valueAccessor()); 39520 39521 if (isLoading) { 39522 $(element).addClass('global-loading'); 39523 $(element).removeClass('global-loading-done'); 39524 } else { 39525 $(element).addClass('global-loading-done'); 39526 } 39527 } 39528};; 39529/// <reference path="../../_references.js" /> 39530 39531ko.bindingHandlers.googleMap = { 39532 init: function (element, valueAccessor, allBindingsAccessor, viewModel) { 39533 var options = valueAccessor(), 39534 latitude = options.lat || null, 39535 longtitude = options.long || null; 39536 39537 var mapCenter = { 39538 lat: latitude, lng: longtitude 39539 }; 39540 39541 var map = new google.maps.Map(element, { 39542 zoom: 16, 39543 center: mapCenter, 39544 disableDefaultUI: true 39545 }); 39546 39547 var marker = new google.maps.Marker({ 39548 position: mapCenter 39549 }); 39550 39551 marker.setMap(map); 39552 } 39553 39554};; 39555/// <reference path="../../_references.js" /> 39556 39557/*jslint this:true */ 39558(function (window) { 39559 39560 var ko = window.ko; 39561 39562 var _serverContext = window._serverContext; 39563 39564 var $ = window.jQuery; 39565 39566 ko.bindingHandlers.languageSwitcher = { 39567 39568 init: function (element, valueAccessor) { 39569 39570 var thisLang = valueAccessor(); 39571 39572 var switcherURL = "/languageswitcher/" + thisLang; 39573 39574 if (thisLang === _serverContext.LanguageCode) { 39575 39576 if ($(element).data("active-hide")) { 39577 $(element).hide(); 39578 } else { 39579 $(element).addClass("header__right-language-link--active"); 39580 $(element).attr("disabled", "disabled"); 39581 } 39582 } else { 39583 39584 $(element).click(function () { 39585 window.location.href = switcherURL + "?url=" + window.location.pathname + encodeURIComponent(window.location.search); 39586 }); 39587 } 39588 39589 } 39590 }; 39591 39592}(this));; 39593/// <reference path="../_references.js" /> 39594 39595ko.bindingHandlers.levelTabsSections = { 39596 init: function (element, valueAccessor, allBindings, viewModel) { 39597 var $elem = $(element), 39598 options = valueAccessor(), 39599 $container = options.container != null ? $(container) : $elem, 39600 children = options.children || "", 39601 classToAdd = options.classToAdd || "modified"; 39602 39603 $container.children(children).find(".article-listing__header").parents(children).siblings().addClass(classToAdd); 39604 } 39605}; 39606;
39607/// <reference path="../../_references.js" /> 39608 39609ko.bindingHandlers.main = { 39610 update: function (element, valueAccessor, allBindings, viewModel) { 39611 //function that runs when any dependency in the valueAccessor changes 39612 39613 var page = ko.unwrap(valueAccessor()); 39614 var $main = $(element); 39615 var templateContainerClass = 'template-container'; 39616 39617 var scrollTo = function (elementID) { 39618 39619 var headerHeight = $("header").outerHeight(); 39620 39621 var element = $("a[name='" + elementID + "'], #" + elementID); 39622 39623 var scroll = function () { 39624 $('html, body').animate({ 39625 scrollTop: element.offset().top - headerHeight + 'px' 39626 }, 0); 39627 }; 39628 39629 if (element.length > 0) { 39630 scroll(); 39631 } 39632 }; 39633 39634 //if this is the server page, kick out 39635 if (page.serverPage !== true) { 39636 39637 var addPage = function () { 39638 //setup the new template container 39639 //var $tmplCnt = $('<div>').addClass(templateContainerClass).attr('id', page.id).delay(500).addClass('fade-in'); 39640 var $tmplCnt = $('<div>').addClass(templateContainerClass).attr('id', page.id); 39641 39642 //add the html from the new page 39643 $tmplCnt.html(page.html); 39644 39645 //start fading out the previous page 39646 //$main.children('.' + templateContainerClass).eq(0).addClass('fade-out'); 39647 39648 //add the new page to the DOM! 39649 $main.append($tmplCnt); 39650 39651 //scroll to top, if we don't have a hash 39652 if (!page.hash) { 39653 window.scrollTo(0, 0); 39654 } else { 39655 scrollTo(page.hash); 39656 } 39657 39658 //add combined scripts 39659 var $scripts = $('<div/>').attr('id', 'script-zone-for--' + page.id).html(page.scripts_combined); 39660 $tmplCnt.append($scripts); 39661 39662 39663 //apply the global viewmodel bindings to the new page 39664 ko.applyBindings(APP, document.getElementById(page.id)) 39665 39666 //wait 1s, until some animations finish, then remove the old page from the DOM 39667 //setTimeout(function () { 39668 var $disposedPage = $main.children('.' + templateContainerClass).eq(0) 39669 ko.cleanNode($disposedPage[0]); 39670 ko.removeNode($disposedPage[0]); 39671 //}, 1000); 39672 39673 APP.Router.afterPageLoaded(); 39674 }; 39675 39676 //if there is still two templates, wait till it's gone 39677 if ($main.children('.' + templateContainerClass).length > 1) { 39678 39679 //check every 100ms 39680 var interval = setInterval(function () { 39681 39682 if ($main.children('.' + templateContainerClass).length < 2) { 39683 addPage(); 39684 clearInterval(interval); 39685 } 39686 }, 100) 39687 } else { 39688 addPage(); 39689 } 39690 39691 } 39692 39693 } 39694 39695}; 39696; 39697/// <reference path="../_references.js" /> 39698 39699ko.bindingHandlers.mobileMenuExpand = { 39700 init: function (element, valueAccessor, allBindings, viewModel) { 39701 //function runs when element is added to the DOM 39702 $(element).click(function () { 39703 $('.mobile-menu').toggleClass('open'); 39704 }) 39705 $('#nav-icon').click(function () { 39706 $(this).toggleClass('open'); 39707 $('.menu').toggleClass('show'); 39708 }); 39709 }, 39710 39711}; 39712 39713ko.bindingHandlers.mobileSublistExpand = { 39714 init: function (element, valueAccessor, allBindings, viewModel) { 39715 //function runs when element is added to the DOM 39716 $(element).click(function () { 39717 $(element).toggleClass('expanded') 39718 var elParent = $(this).parent(); 39719 var grandParent = elParent.parent(); 39720 grandParent.children().toggleClass('open'); 39721 }) 39722 }, 39723 39724}; 39725; 39726/// <reference path="../_references.js" /> 39727 39728ko.bindingHandlers.mobileMenuTabindex = { 39729 update: function (element, valueAccessor, allBindings, viewModel) { 39730 var $elem = $(element), 39731 options = valueAccessor(); 39732 39733 if (options) { 39734 $elem.find('a').attr('tabindex', '0') 39735 } else { 39736 $elem.find('a').attr('tabindex', '-1') 39737 } 39738 } 39739}; 39740;
39741/// <reference path="../_references.js" /> 39742 39743ko.bindingHandlers.mobileSubNavExpand = { 39744 init: function (element, valueAccessor, allBindings, viewModel) { 39745 //function runs when element is added to the DOM 39746 $(element).click(function () { 39747 $('.subNav-container').toggleClass('open'); 39748 $(this).toggleClass('open'); 39749 }) 39750 }, 39751}; 39752 39753ko.bindingHandlers.mobileSubNavCollapse = { 39754 init: function (element, valueAccessor, allBindings, viewModel) { 39755 //function runs when element is added to the DOM 39756 var lastButton = null; 39757 39758 $(element).click(function () { 39759 $('.subNav-container').removeClass('open'); 39760 $('button').removeClass('open'); 39761 }) 39762 $(element).keydown(function (e) { 39763 if (e.which === 40) { 39764 $('.news--header__link').focus(); 39765 //create variable to remember last tabbed item here. 39766 lastButton = e.target; 39767 console.log(lastButton); 39768 $('.badge-link').blur(function () { 39769 lastButton.focus(); 39770 }) 39771 } 39772 }) 39773 $('.badge-link').keydown(function (e) { 39774 if (e.which === 40) { 39775 $('.event-details-title').filter(":first").focus(); 39776 39777 } 39778 }) 39779 }, 39780 39781}; 39782 39783 39784; 39785/// <reference path="../_references.js" /> 39786 39787ko.bindingHandlers.openModaal = { 39788 init: function (element, valueAccessor, allBindings, viewModel) { 39789 var $elem = $(element), 39790 target = valueAccessor(); 39791 39792 $elem.modaal(); 39793 } 39794}; 39795; 39796/// <reference path="../_references.js" /> 39797 39798ko.bindingHandlers.search = { 39799 init: function (element, valueAccessor, allBindings, viewModel) { 39800 //function runs when element is added to the DOM 39801 //console.log(element) 39802 $(element).click(function () { 39803 $(".logo__container").toggleClass("hide"); 39804 $(".header-functions__contact").toggleClass("hide") 39805 $(this).toggleClass("open"); 39806 $('input.search').val('Search'); 39807 $('.header-functions__search').css('max-width', 'unset'); 39808 var classState = $(this).attr('class'); 39809 if (classState === "header-functions__search") { 39810 $('input.search').val(''); 39811 39812 } 39813 39814 ///when the element is closed, remove search value 39815 }) 39816 } 39817 39818}; 39819 39820; 39821/// <reference path="../_references.js" /> 39822 39823ko.bindingHandlers.selectize = { 39824 init: function (element, valueAccessor, allBindings, viewModel) { 39825 var $elem = $(element), 39826 options = valueAccessor(), 39827 items = options.items || null; 39828 39829 $elem.selectize({ 39830 valueField: 'TabIndex', 39831 labelField: 'Title', 39832 hideSelected: true, 39833 options: items, 39834 render: { 39835 option: function (data, escape) { 39836 return '<div class="option">' 39837 + (data.Icon !== null ? '<span class="option__icon ' + escape(data.Icon) + '"></span>' : "") 39838 + '<span class="option__title title">' + escape(data.Title) + '</span>' 39839 + '</div>'; 39840 } 39841 }, 39842 onInitialize: function () { 39843 var self = this; 39844 39845 self.$control_input.attr('readonly', true); 39846 self.setValue(1); 39847 }, 39848 onChange: function (value, $item) { 39849 //HACK - I'm so sorry 39850 //TODO: Make this work with the binding. Instead of changing the classes change an observable 39851 $('[data-toggle-click-index="tab-' + value + '"]').click(); 39852 } 39853 }) 39854 39855 } 39856}; 39857; 39858/// <reference path="../_references.js" /> 39859 39860/*jslint this:true */ 39861(function (window) { 39862 39863 var ko = window.ko; 39864 39865 var $ = window.jQuery; 39866 39867 var defaultSlider = "slick"; 39868 39869 var swiperAdapter = { 39870 39871 createSlider: function (element, options) { 39872 39873 var self = this; 39874 39875 var selectorClass = $(element).attr("class"); 39876 39877 var sliderID = $(element).attr("id"); 39878 39879 var swiperSelector = !!sliderID 39880 ? "#" + sliderID 39881 : ""; 39882 39883 swiperSelector += !!selectorClass 39884 ? "." + selectorClass.replace(/\s+/gi, ".") 39885 : ""; 39886 39887 var swiperOptions = {}; 39888 39889 var registerParentCallback = function (options, eventCallback) { 39890 39891 var eventHandler = function () { 39892 39893 var newSlideIndex = !parentInstance 39894 ? -1 39895 : parentInstance.realIndex + 1; 39896 39897 eventCallback(parentInstance, newSlideIndex); 39898 39899 return true; 39900 }; 39901 39902 if (!!options.parentSliderID) { 39903 39904 var parentSliderElem = $("#" + options.parentSliderID); 39905 39906 var parentInstance = parentSliderElem[0].swiper; 39907 39908 parentInstance.on("slideChangeStart", eventHandler); 39909 } 39910 }; 39911 39912 var slider = null; 39913 39914 if (!!swiperSelector) { 39915 39916 swiperOptions.preventClicks = false; 39917 swiperOptions.paginationClickable = true; 39918 swiperOptions.slidesPerView = options.slidesPerView; 39919 swiperOptions.spaceBetween = options.spaceBetween; 39920 swiperOptions.effect = options.effect; 39921 swiperOptions.centeredSlides = "centeredSlides" in o
39921ptions ? options.centeredSlides : false; 39922 39923 if (options.speed > 0) { 39924 swiperOptions.autoplay = options.speed; 39925 swiperOptions.autoplayDisableOnInteraction = false; 39926 swiperOptions.lazyLoading = true; 39927 } 39928 39929 registerParentCallback(options, function (instance, newSlideIndex) { 39930 39931 console.log(newSlideIndex); 39932 39933 self.sliderGoTo(swiperSelector, newSlideIndex); 39934 }); 39935 39936 swiperOptions.loop = "loop" in options ? options.loop : true; 39937 39938 slider = new window.Swiper(swiperSelector, swiperOptions); 39939 39940 } else { 39941 slider = null; 39942 } 39943 }, 39944 39945 sliderGoTo: function (sliderSelector, slideIndex) { 39946 39947 var sliderElem = $(sliderSelector); 39948 39949 var instance = sliderElem[0].swiper; 39950 39951 instance.slideTo(slideIndex); 39952 }, 39953 39954 sliderNext: function (sliderSelector) { 39955 39956 var sliderElem = $(sliderSelector); 39957 39958 var instance = sliderElem[0].swiper; 39959 39960 instance.slideNext(); 39961 }, 39962 39963 sliderPrevious: function (sliderSelector) { 39964 39965 var sliderElem = $(sliderSelector); 39966 39967 var instance = sliderElem[0].swiper; 39968 39969 instance.slidePrev(); 39970 }, 39971 39972 registerEventHandlers: function (sliderSelector, eventCallback) { 39973 39974 var sliderElem = $(sliderSelector); 39975 39976 var instance = sliderElem[0].swiper; 39977 39978 var eventHandler = function () { 39979 39980 var newSlideIndex = !instance 39981 ? -1 39982 : instance.realIndex + 1; 39983 39984 eventCallback(instance, newSlideIndex); 39985 39986 return true; 39987 }; 39988 39989 instance.on("slideChangeStart", eventHandler); 39990 39991 eventHandler(); 39992 } 39993 }; 39994 39995 var slickAdapter = { 39996 39997 createSlider: function (element, options) { 39998 39999 var $elem = $(element); 40000 40001 var slickOptions = {}; 40002 40003 //var registerParentCallback = function (options, eventCallback) { 40004 40005 // var eventHandler = function () { 40006 40007 // var newSlideIndex = !parentInstance 40008 // ? -1 40009 // : parentInstance.realIndex + 1; 40010 40011 // eventCallback(parentInstance, newSlideIndex); 40012 40013 // return true; 40014 // }; 40015 40016 // if (!!options.parentSliderID) { 40017 40018 // var parentSliderElem = $("#" + options.parentSliderID); 40019 40020 // var parentInstance = parentSliderElem[0].swiper; 40021 40022 // parentInstance.on("afterChange", eventHandler); 40023 // } 40024 //}; 40025 40026 if (options.speed > 0) { 40027 slickOptions.autoplay = true; 40028 slickOptions.autoplaySpeed = options.speed; 40029 } 40030 40031 slickOptions.lazyLoad = "ondemand"; 40032 slickOptions.prevArrow = ""; 40033 slickOptions.nextArrow = ""; 40034 slickOptions.dots = options.dots; 40035 40036 $($elem).slick(slickOptions); 40037 40038 //registerParentCallback(options, function (instance, newSlideIndex) { 40039 40040 // console.log(newSlideIndex); 40041 40042 // self.sliderGoTo(swiperSelector, newSlideIndex); 40043 //}); 40044 }, 40045 40046 sliderGoTo: function (sliderSelector, slideIndex) { 40047 40048 var sliderElem = $(sliderSelector); 40049 40050 sliderElem.slick("slickGoTo", slideIndex - 1); 40051 }, 40052 40053 sliderNext: function (sliderSelector, slideIndex) { 40054 40055 // TODO: implement this 40056 }, 40057 40058 sliderPrevious: function (sliderSelector, slideIndex) { 40059 40060 // TODO: implement this 40061 }, 40062 40063 registerEventHandlers: function (sliderSelector, eventCallback) { 40064 40065 // TODO: implement on slick 40066 eventCallback(null, -1); 40067 } 40068 }; 40069 40070 var owlcarouselAdapter = { 40071 40072 createSlider: function (element, options) { 40073 40074 var $elem = $(element); 40075 40076 var carouselElem = $(".owl-carousel", $elem); 40077 40078 var owlOptions = {}; 40079 40080 if (!$.fn.owlCarousel) { 40081 40082 return; 40083 } 40084 40085 var numOfSlides = $('.owl-carousel > div', $(element)).length; 40086 40087 if (numOfSlides > 1) { 40088 owlOptions.loop = true; 40089 } else { 40090 owlOptions.mouseDrag = false; 40091 owlOptions.touchDrag = false; 40092 owlOptions.pullDrag = false; 40093 } 40094 40095 owlOptions.autoplay = true; 40096 owlOptions.navigation = false; 40097 owlOptions.autoplayTimeout = options.speed; 40098 owlOptions.paginationSpeed = 400; 40099 owlOptions.items = 1; 40100 owlOptions.lazyLoad = true; 40101 40102 carouselElem.owlCarousel(owlOptions); 40103 }, 40104 40105 sliderGoTo: function (sliderSelector, slideIndex) { 40106 40107 var sliderElem = $(".owl-carousel", sliderSelector).data("owlCarousel"); 40108 40109 sliderElem.to(slideIndex - 1); 40110 }, 40111 40112 sliderNext: function (sliderSelector, slideIndex) { 40113 40114 var sliderElem = $(sliderSelector); 40115 40116 sliderElem = $(".owl-carousel", sliderSelector).data("owlCarousel"); 40117 40118 sliderElem.next(); 40119 }, 40120 40121 sliderPrevious: function (sliderSelector, slideIndex) { 40122 40123 var sliderElem = $(sliderSelector); 40124 40125 sliderElem = $(".owl-carousel", sliderSelector).data("owlCarousel"); 40126 40127 sliderElem.prev(); 40128 }, 40129 40130 registerEventHandlers: function (sliderSelector, eventCallback) { 40131 40132 var sliderElem = $(".owl-carousel", sliderSelector).data("owlCarousel"); 40133 40134 $(".owl-carousel", sliderSelector).on("changed.owl.carousel", function (evt) { 40135 40136 var newSlideIndex = evt.item.index - 1; 40137 40138 eventCallback(null, newSlideIndex); 40139 }); 40140 } 40141 }; 40142 40143 var sliders = { 40144 40145 "swiper": swiperAdapter, 40146 40147 "slick": slickAdapter, 40148 40149 "owlcarousel2": owlcarouselAdapter 40150 }; 40151
40152 ko.bindingHandlers.slider = { 40153 40154 init: function (element, valueAccessor) { 40155 40156 var $ = window.jQuery; 40157 40158 var options = ko.unwrap(valueAccessor()) || {}; 40159 40160 if (sliders.hasOwnProperty(defaultSlider)) { 40161 40162 sliders[defaultSlider].createSlider(element, options); 40163 } 40164 } 40165 }; 40166 40167 ko.bindingHandlers.sliderGoTo = { 40168 40169 init: function (element, valueAccessor, allBindings) { 40170 40171 var $ = window.jQuery; 40172 40173 var $elem = $(element); 40174 40175 var sliderSelector = ko.unwrap(valueAccessor()); 40176 40177 var sliderElem = null; 40178 40179 var addActiveClass = function (classToAdd) { 40180 40181 $($elem.siblings()).removeClass(classToAdd); 40182 40183 $elem.addClass(classToAdd); 40184 }; 40185 40186 var slideGoToOptions = allBindings.get("sliderGoToOptions"); 40187 40188 var slideIndex = parseInt(slideGoToOptions.slideIndex, 10); 40189 40190 $elem.on("click", function (evt) { 40191 evt.preventDefault(); 40192 40193 if (sliders.hasOwnProperty(defaultSlider)) { 40194 sliders[defaultSlider].sliderGoTo(sliderSelector, slideIndex); 40195 } 40196 40197 addActiveClass(slideGoToOptions.classToAdd); 40198 }); 40199 40200 if (sliders.hasOwnProperty(defaultSlider)) { 40201 40202 if (sliders[defaultSlider].hasOwnProperty("registerEventHandlers")) { 40203 40204 sliders[defaultSlider].registerEventHandlers(sliderSelector, function (instance, newSlideIndex) { 40205 40206 if (newSlideIndex === slideIndex) { 40207 40208 addActiveClass(slideGoToOptions.classToAdd); 40209 } 40210 }); 40211 } 40212 } 40213 } 40214 }; 40215 40216 ko.bindingHandlers.sliderNext = { 40217 40218 init: function (element, valueAccessor, allBindings) { 40219 40220 var sliderSelector = ko.unwrap(valueAccessor()); 40221 40222 var $elem = $(element); 40223 40224 var sliderElem = null; 40225 40226 $elem.on("click", function (evt) { 40227 40228 evt.preventDefault(); 40229 40230 if (sliders.hasOwnProperty(defaultSlider)) { 40231 sliders[defaultSlider].sliderNext(sliderSelector); 40232 } 40233 }); 40234 } 40235 }; 40236 40237 ko.bindingHandlers.sliderPrevious = { 40238 40239 init: function (element, valueAccessor, allBindings) { 40240 40241 var sliderSelector = ko.unwrap(valueAccessor()); 40242 40243 var $elem = $(element); 40244 40245 var sliderElem = null; 40246 40247 $elem.on("click", function (evt) { 40248 evt.preventDefault(); 40249 40250 if (sliders.hasOwnProperty(defaultSlider)) { 40251 sliders[defaultSlider].sliderPrevious(sliderSelector); 40252 } 40253 }); 40254 } 40255 }; 40256 40257}(this));; 40258/// <reference path="../_references.js" /> 40259 40260ko.bindingHandlers.showSpotlightSection = { 40261 init: function (element, valueAccessor, allBindings, viewModel) { 40262 //function runs when element is added to the DO 40263 40264 $(element).click(function (e) { 40265 function showSection(n) { 40266 console.log(clicked) 40267 var sections = $('.spotlight-flex-container'); 40268 var tabs = $('.tab-desk'); 40269 if (n > sections.length) { 40270 sectionIndex = 1; 40271 } 40272 if (n < 1) { 40273 sectionIndex = sections.length; 40274 } 40275 for (var i = 0; i < sections.length; i++) { 40276 sections[i].style.display = "none"; 40277 } 40278 for (var i = 0; i < tabs.length; i++) { 40279 tabs[i].className = tabs[i].className.replace(' tab-open', 'tab-desk'); 40280 } 40281 sections[sectionIndex - 1].style.display = "flex"; 40282 tabs[sectionIndex - 1].className += " tab-open"; 40283 40284 } 40285 var clicked = e.target.className 40286 $(this).toggleClass(""); 40287 if (clicked === "spotlight-tab") { 40288 sectionIndex = 1; 40289 } 40290 if (clicked === "schools-tab") { 40291 sectionIndex = 2; 40292 } 40293 if (clicked === "parents-tab") { 40294 sectionIndex =3; 40295 } 40296 if (clicked === "special-tab") { 40297 sectionIndex = 4; 40298 } 40299 if (clicked === "public-tab") { 40300 sectionIndex = 5; 40301 } 40302 if (clicked === "employees-tab") { 40303 sectionIndex = 6; 40304 } 40305 if (clicked === "facebook-tab") { 40306 sectionIndex = 7; 40307 } 40308 if (clicked === "fa fa-facebook") { 40309 sectionIndex = 7; 40310 } 40311 if (clicked === "twitter-tab") { 40312 sectionIndex = 8; 40313 } 40314 if (clicked === "fa fa-twitter") { 40315 sectionIndex = 8; 40316 } 40317 showSection(sectionIndex); 40318 40319 }) 40320 40321 var sectionIndex = 1; 40322 showSection(sectionIndex); 40323 40324 40325 function showSection(n) { 40326 var sections = $('.spotlight-flex-container'); 40327 var tabs = $('.tab-desk'); 40328 if (n > sections.length) { 40329 sectionIndex = 1; 40330 } 40331 if (n < 1) { 40332 sectionIndex = sections.length; 40333 } 40334 for (var i = 0; i < sections.length; i++) { 40335 sections[i].style.display = "none"; 40336 } 40337 for (var i = 0; i < tabs.length; i++) { 40338 tabs[i].className = tabs[i].className.replace(' tab-open', 'tab-desk'); 40339 } 40340 sections[sectionIndex - 1].style.display = "flex"; 40341 tabs[sectionIndex - 1].className += " tab-open"; 40342 40343 } 40344 } 40345 40346}; 40347;
40348/// <reference path="../_references.js" /> 40349 40350ko.bindingHandlers.tabletMenu = { 40351 init: function (element, valueAccessor, allBindings, viewModel) { 40352 //function runs when element is added to the DOM 40353 //console.log(element) 40354 $(element).click(function () { 40355 $(this).toggleClass("open"); 40356 }); 40357 } 40358}; 40359; 40360/// <reference path="../_references.js" /> 40361 40362/*jslint this:true */ 40363(function (window) { 40364 40365 var ko = window.ko; 40366 40367 var $ = window.jQuery; 40368 40369 ko.bindingHandlers.toggleOnClick = { 40370 40371 init: function (element, valueAccessor) { 40372 40373 var $elem = $(element); 40374 40375 var options = ko.unwrap(valueAccessor()); 40376 40377 var keepActive = options.keepActive || false; 40378 40379 var tabClassToAdd = options.tabClassToAdd || "active"; 40380 40381 var tabContentClassToAdd = options.tabContentClassToAdd || options.tabClassToAdd || "active"; 40382 40383 var containerClassToAdd = options.containerClassToAdd || ""; 40384 40385 var tabGroup = options.tabGroup || ""; 40386 40387 var showFirst = "showFirst" in options 40388 ? options.showFirst 40389 : false; 40390 40391 var tabsFilter = !!tabGroup 40392 ? "[data-toggle-click='true'][data-toggle-click-group='" + tabGroup + "']" 40393 : "[data-toggle-click='true']"; 40394 40395 var tabs = $(tabsFilter, $elem); 40396 40397 var hideTab = function (tabName) { 40398 40399 //hide all tab contents 40400 $("[data-toggle-click-content='true']", $elem).removeClass(tabContentClassToAdd); //content 40401 $("[data-toggle-click='true']", $elem).removeClass(tabClassToAdd); //tab 40402 40403 var $tabContentToActivate = $("[data-toggle-click-content='true'][data-toggle-click-index='" + tabName + "']"); 40404 var $tabToActive = $("[data-toggle-click='true'][data-toggle-click-index='" + tabName + "']"); 40405 40406 //show active 40407 $tabContentToActivate.removeClass(tabContentClassToAdd); //content 40408 40409 //tab 40410 $tabToActive.removeClass(tabClassToAdd); 40411 40412 if (!!containerClassToAdd) { 40413 $elem.removeClass(containerClassToAdd); 40414 } 40415 }; 40416 40417 var showTab = function (tabName) { 40418 40419 //hide all tab contents 40420 $("[data-toggle-click-content='true']", $elem).removeClass(tabContentClassToAdd); //content 40421 $("[data-toggle-click='true']", $elem).removeClass(tabClassToAdd); //tab 40422 40423 var $tabContentToActivate = $("[data-toggle-click-content='true'][data-toggle-click-index='" + tabName + "']"); 40424 var $tabToActive = $("[data-toggle-click='true'][data-toggle-click-index='" + tabName + "']"); 40425 40426 //show active 40427 $tabContentToActivate.addClass(tabContentClassToAdd); //content 40428 40429 //tab 40430 $tabToActive.addClass(tabClassToAdd); 40431 40432 if (!!containerClassToAdd) { 40433 $elem.addClass(containerClassToAdd); 40434 } 40435 }; 40436 40437 tabs.click(function (evt) { 40438 evt.preventDefault(); 40439 var tabName = $(this).attr("data-toggle-click-index"); 40440 40441 if ($(this).hasClass(tabClassToAdd)) { 40442 40443 if (!keepActive) { 40444 hideTab(tabName); 40445 } 40446 } else { 40447 showTab(tabName); 40448 } 40449 40450 }); 40451 40452 if (!!showFirst) { 40453 40454 var firstContent = $("[data-toggle-click-content='true']:first-child", $elem); 40455 40456 var firstTabName = ""; 40457 40458 if (firstContent.length > 0) { 40459 40460 firstTabName = firstContent.data("toggle-click-index"); 40461 40462 showTab(firstTabName); 40463 } 40464 } 40465 } 40466 }; 40467 40468}(this));; 40469/// <reference path="../_references.js" /> 40470 40471ko.bindingHandlers.warningModal = { 40472 init: function (element, valueAccessor, allBindings, viewModel) { 40473 //function runs when element is added to the DOM 40474 40475 $(element).on('click', function (event) { 40476 event.preventDefault(); 40477 $('#warning-modal').iziModal('open', { 40478 //transitionIn: 'fadeInDown', 40479 //transitionOut: 'flipOutX' 40480 }); 40481 }); 40482 40483 $("#warning-modal").iziModal(); 40484 40485 } 40486}; 40487;
40488/// <reference path="../_references.js" /> 40489var VM = APP.ViewModels; 40490 40491VM.AppModel = function () { 40492 var self = this; 40493 40494 self.page = ko.observable(window._serverContext.Page); 40495 40496 self.sections = ko.observableArray([]); 40497 40498 self.slideInView = null; 40499 self.routeScrollInProgress = false; 40500 40501 self.section = ko.observable(""); 40502 self.updatedSection = ko.pureComputed(function () { 40503 return self.section(); 40504 }); 40505 40506 self.clientPageRequest = ko.observable(null); 40507 40508 //close all the global elements like searchbar or modals 40509 self.closeAllGlobalElements = function () { 40510 //self.open.searchbar(false); 40511 //self.open.splashSearch(false); 40512 } 40513 40514 //function called to check if the page requires authentication 40515 self.checkPageAuthentication = function (page) { 40516 40517 if (!page) { 40518 page = self.page(); 40519 } 40520 40521 if (page.requiresAuth) { 40522 self.Router.RedirectToLogin(); 40523 return true; 40524 } 40525 40526 return false; 40527 } 40528 40529 self.globalLoading = ko.pureComputed({ 40530 read: function () { 40531 40532 var clientPageRequest = ko.unwrap(self.clientPageRequest); 40533 var ready = ko.unwrap(self.appReady); 40534 40535 return clientPageRequest != null || !ready; 40536 }, 40537 owner: this 40538 }); 40539 40540 self.pageIndex = 0; 40541 40542 self.newPageID = function () { 40543 self.pageIndex++; 40544 return 'page-' + self.pageIndex; 40545 } 40546 40547 self.initialLoading = ko.pureComputed({ 40548 read: function () { 40549 var ready = ko.unwrap(self.appReady); 40550 return !ready; 40551 }, 40552 owner: this 40553 }); 40554 40555 /// 40556 //on ready 40557 /// 40558 self.appReady = ko.observable(false); 40559 self.onReady = function () { 40560 APP.Router.setupRoutes(); 40561 40562 //APP.Account.Initialize(function () { 40563 // self.appReady(true); 40564 //}); 40565 40566 self.appReady(true); 40567 }; 40568 40569 // Menu variable 40570 self.mobileMenu = { 40571 open: ko.observable(false).toggleable() 40572 }; 40573 40574 self.mobileSearch = { 40575 open: ko.observable(false).toggleable() 40576 }; 40577 40578}; 40579 40580; 40581ko.components.register('contact-us', { 40582 viewModel: function (params) { 40583 function ContactUs(params) { 40584 var self = this; 40585 40586 self.state = { 40587 loading: ko.observable(false), 40588 ready: ko.observable(false), 40589 error: ko.observable(false), 40590 submitted: ko.observable(false), 40591 reset: function () { 40592 self.state.loading(false); 40593 self.state.ready(false); 40594 self.state.error(false); 40595 self.state.submitted(false); 40596 } 40597 }; 40598 40599 self.data = { 40600 referenceName: params.referenceName || "ContactUs" 40601 } 40602 40603 self.form = { 40604 firstName: ko.observable(""), 40605 lastName: ko.observable(""), 40606 emailAddress: ko.observable(""), 40607 departmentOrTopic: ko.observable(""), 40608 message: ko.observable(""), 40609 submit: self.submitForm, 40610 error: ko.observable() 40611 }; 40612 40613 self.init(params); 40614 }; 40615 40616 ko.utils.extend(ContactUs.prototype, { 40617 init: function (params) { 40618 var self = this; 40619 40620 self.state.loading(true); 40621 40622 //Do something 40623 40624 self.state.loading(false); 40625 40626 }, 40627 submitForm: function () { 40628 var self = this; 40629 40630 self.state.loading(true); 40631 40632 self.state.error(false); 40633 40634 var contactUsForm = new Agility.UGC.API.BooleanFeedback(); 40635 40636 contactUsForm.RecordTypeName = self.data.referenceName; 40637 40638 contactUsForm.FirstName = ko.unwrap(self.form.firstName); 40639 contactUsForm.LastName = ko.unwrap(self.form.lastName); 40640 contactUsForm.EmailAddress = ko.unwrap(self.form.emailAddress); 40641 contactUsForm.Message = ko.unwrap(self.form.message); 40642 contactUsForm.DepartmentOrTopic = ko.unwrap(self.form.departmentOrTopic); 40643 40644 Agility.UGC.API.SaveRecord(contactUsForm, function (data) { 40645 40646 if (data.ResponseType != Agility.UGC.API.ResponseType.OK) { 40647 //error occurred 40648 self.form.error(data.Message); 40649 self.state.error(true); 40650 } else { 40651 console.log("Form submitted sucessfully." + data.Message); 40652 self.state.submitted(true); 40653 } 40654 40655 self.state.loading(false); 40656 40657 }); 40658 40659 }, 40660 dispose: function () { 40661 var self = this; 40662 } 40663 40664 }); 40665
40666 return new ContactUs(params); 40667 40668 }, 40669 template: { 40670 element: 'contact-us-tmpl' 40671 } 40672});; 40673ko.components.register('event-details', { 40674 viewModel: function (params) { 40675 function EventDetails(params) { 40676 var self = this; 40677 40678 self.state = { 40679 loading: ko.observable(false), 40680 ready: ko.observable(false), 40681 error: ko.observable(false), 40682 submitted: ko.observable(false), 40683 reset: function () { 40684 self.state.loading(false); 40685 self.state.ready(false); 40686 self.state.error(false); 40687 self.state.submitted(false); 40688 } 40689 }; 40690 40691 self.data = { 40692 locationTerm: params.location 40693 } 40694 40695 self.searchHTML5 = "HTML5"; 40696 self.searchGoogleMaps = "Google"; 40697 self.searchType = ko.observable(self.searchHTML5); 40698 self.geocoder = null; 40699 self.locations = ko.observableArray([]); 40700 self.longitude = ko.observable(null); 40701 self.latitude = ko.observable(null); 40702 40703 self.searchByLocationTerm = function (onSuccess) { 40704 40705 self.searchType(self.searchGoogleMaps); 40706 40707 if (self.geocoder == null) { 40708 self.geocoder = new google.maps.Geocoder(); 40709 } 40710 40711 self.geocoder.geocode({ 40712 'address': self.data.locationTerm 40713 }, function (results, status) { 40714 if (status == google.maps.GeocoderStatus.OK && results != null && results.length > 0) { 40715 40716 self.searchByLatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng()) 40717 40718 if (onSuccess) 40719 onSuccess(); 40720 } 40721 }); 40722 }; 40723 40724 self.searchByLatLng = function (latitude, longitude) { 40725 self.latitude(latitude) 40726 self.longitude(longitude) 40727 }; 40728 40729 self.init(params); 40730 }; 40731 40732 ko.utils.extend(EventDetails.prototype, { 40733 40734 init: function (params) { 40735 var self = this; 40736 40737 self.state.loading(true); 40738 40739 //Do something 40740 self.searchByLocationTerm(function () { 40741 self.state.loading(false); 40742 self.state.ready(true); 40743 }); 40744 40745 }, 40746 40747 dispose: function () { 40748 var self = this; 40749 } 40750 40751 }); 40752 40753 return new EventDetails(params); 40754 40755 }, 40756 template: { 40757 element: 'event-details-tmpl' 40758 } 40759});; 40760ko.components.register('school-search', { 40761 viewModel: function (params) { 40762 function SchoolSearch(params) { 40763 var self = this; 40764 40765 self.state = { 40766 loading: ko.observable(false), 40767 ready: ko.observable(false), 40768 error: ko.observable(false), 40769 noSchoolsResult: ko.observable(false), 40770 reset: function () { 40771 self.state.loading(false); 40772 self.state.ready(false); 40773 self.state.error(false); 40774 self.state.noSchoolsResult(false); 40775 } 40776 }; 40777 40778 self.data = { 40779 programs: ko.observableArray(JSON.parse(params.programs)), 40780 schoolResults: ko.observableArray([]) 40781 } 40782 40783 self.form = { 40784 selectedProgram: ko.observable(params.preSelectionProgramsIDs || null), 40785 selectedLevel: ko.observable(params.preSelectionLevelsIDs || null), 40786 selectedBorough: ko.observable(params.preSelectionBoroughsIDs || null) 40787 }; 40788 40789 //self.form.selectedProgram.subscribe(function(newvalue) { 40790 // return self.searchFilterChange(); 40791 //}); 40792 40793 self.init(params); 40794 }; 40795 40796 ko.utils.extend(SchoolSearch.prototype, { 40797 init: function (params) { 40798 var self = this; 40799 40800 self.getSchools(); 40801 40802 self.filterPrograms(); 40803 40804 }, 40805 search: function() { 40806 var self = this; 40807 40808 self.searchFilterChange(); 40809 }, 40810 searchFilterChange: function () { 40811 40812 var self = this; 40813 40814 self.getSchools(); 40815 40816 self.state.loading(true); 40817 40818 self.state.error(false); 40819 40820 }, 40821 40822 filterPrograms: function () { 40823 var self = this; 40824 40825 self.state.loading(true); 40826 40827 var url = "/SchoolSearch/GetSchoolPrograms"; 40828 40829 var data = { 40830 academicLevelId: ko.unwrap(self.form.selectedLevel) 40831 }; 40832 40833 self.ajaxRequest = CORE.Get(url, data, 40834 function (result) { 40835 40836 if (!result.IsError) { 40837 self.data.programs(result); 40838 } 40839 }, 40840 function (err, status, errorMessage) { }, 40841 function () { 40842 self.state.loading(false); 40843 });
40844 40845 return self.ajaxRequest; 40846 }, 40847 40848 getSchools: function () { 40849 var self = this; 40850 40851 self.state.reset(); 40852 self.state.loading(true); 40853 40854 if (!ko.unwrap(self.form.selectedBorough) && 40855 !ko.unwrap(self.form.selectedProgram) && 40856 !ko.unwrap(self.form.selectedLevel)) { 40857 self.data.schoolResults([]); 40858 } 40859 else { 40860 40861 var url = '/SchoolSearch/GetSchools'; 40862 40863 var prog = ko.unwrap(self.form.selectedProgram); 40864 40865 if (prog) { 40866 prog = prog.Value; 40867 } 40868 40869 var data = { 40870 boroughId: ko.unwrap(self.form.selectedBorough), 40871 programId: prog, 40872 academicLevelId: ko.unwrap(self.form.selectedLevel) 40873 }; 40874 40875 self.ajaxRequest = CORE.Get(url, data, 40876 function (result) { 40877 40878 if (!result.IsError) { 40879 40880 self.data.schoolResults(result.AcademicLevel); 40881 40882 if (ko.unwrap(self.data.schoolResults).length === 0) { 40883 self.state.noSchoolsResult(true); 40884 } 40885 40886 } else { 40887 self.state.noSchoolsResult(true); 40888 } 40889 40890 }, 40891 function (err, status, errorMessage) { }, 40892 function () { 40893 self.state.loading(false); 40894 }); 40895 40896 return self.ajaxRequest; 40897 } 40898 }, 40899 40900 formatSchoolAddress: function (school) { 40901 40902 var schoolAddress = ""; 40903 40904 if (this.hasAddress(school)) { 40905 schoolAddress += school.StreetAddress1 + "<br/>" + school.City + " " + school.PostalCode; 40906 } 40907 40908 return schoolAddress; 40909 40910 }, 40911 40912 hasAddress: function (school) { 40913 40914 var hasAddress = false; 40915 40916 if (school) { 40917 hasAddress = true; 40918 } 40919 40920 return hasAddress; 40921 40922 }, 40923 40924 dispose: function () { 40925 var self = this; 40926 } 40927 40928 }); 40929 40930 return new SchoolSearch(params); 40931 40932 }, 40933 template: { 40934 element: 'school-search-tmpl' 40935 } 40936});; 40937/// <reference path="../_references.js" /> 40938 40939var CORE = APP.Core, 40940 VM = APP.ViewModels, 40941 ROUTER = APP.Router; 40942 40943///////////////////////// 40944// DOM READY 40945///////////////////////// 40946var $win = $(window); 40947 40948$(function () { 40949 40950 ////////////////////////////////////////////////////////////////////////////// 40951 // INIT UGC 40952 ////////////////////////////////////////////////////////////////////////////// 40953 window.InitUGC(); 40954 40955 40956 ////////////////////////////////////////////////////////////////////////////// 40957 // INIT KNOCKOUT 40958 ////////////////////////////////////////////////////////////////////////////// 40959 ko.options.deferUpdates = true; 40960 40961 40962 APP.Router = new VM.RouterModel(); 40963 40964 //kickoff knockout binding 40965 ko.utils.extend(APP, new VM.AppModel()); //store bound instance of APP model in global var 40966 ko.applyBindings(APP, document.getElementById('html')); 40967 40968 //let's go! 40969 APP.onReady(); 40970 40971 40972});; 40973Agility.RegisterNamespace("RegistrationForm"); 40974 40975const PRF = (function (PreregForm, $) { 40976 40977 PreregForm.Init = function (arg) { 40978 // $("#btnCreateAccount").click(createProfile); 40979 } 40980 40981 // 30th september current year 40982 const cutoff = new Date(new Date().getFullYear(), 8, 30); 40983 $("[js-datepicker]").datepicker({ 40984 minDate: "-18y", 40985 changeYear: true, 40986 changeMonth: true, 40987 yearRange: "-21:+0", 40988 onSelect: function () { 40989 $("[js-registration-type]").prop("selectedIndex", 0); 40990 $("[js-registration-type]").trigger("change"); 40991 } 40992 }).focus(function () { 40993 $(".ui-datepicker-next").hide(); 40994 $(".ui-datepicker-prev").hide(); 40995 }); 40996 40997 $("[js-next-step]").on("click", function () { 40998 let nextStep = $(this).data("next-step"); 40999 if ($(".registration-form").valid()) { 41000 $("[data-step=" + (nextStep - 1) + "]").hide(); 41001 $("[data-step=" + nextStep + "]").show(); 41002 } 41003 41004 }); 41005 41006 $("[js-prev-step]").on("click", function () { 41007 let prevStep = $(this).data("prev-step"); 41008 $("[data-step=" + (prevStep + 1) + "]").hide(); 41009 $("[data-step=" + prevStep + "]").show(); 41010 });
41011 41012 // https://stackoverflow.com/questions/4060004/calculate-age-given-the-birth-date-in-the-format-yyyymmdd 41013 $("[js-registration-type]").on("change", function () { 41014 let childDob = new Date($("[js-child-dob]").val()); 41015 var ageDifMs = cutoff.getTime() - childDob.getTime(); 41016 var ageDate = new Date(ageDifMs); // miliseconds from epoch 41017 let age = Math.abs(ageDate.getUTCFullYear() - 1970) 41018 41019 // reset all elements 41020 $("[js-kindergarten-sister-name]").find("input[type=text]").val(""); 41021 $("[js-derogation-gradeone]").find("input[type=checkbox]").prop("checked", false); 41022 $("[js-derogation-kindergarten]").find("input[type=checkbox]").prop("checked", false); 41023 $($("[js-kindergarten-sister]")[1]).trigger("click"); // set to no. 41024 $("[js-derogation-gradeone]").hide(); 41025 $("[js-derogation-kindergarten]").hide(); 41026 $("[js-kindergarten]").hide(); 41027 41028 if ($("[js-registration-type]").val() == "Kindergarten" && age < 5) { // if the child is less than 5 and they have chosen kindergarten show derogation 41029 $("[js-derogation-kindergarten]").show(); 41030 } 41031 if ($("[js-registration-type]").val() == "Kindergarten") { // but always show this if they chose kindergarten 41032 $("[js-kindergarten]").show(); 41033 } 41034 41035 if ($("[js-registration-type]").val() == "Grade 1" && age < 6) { // if they chose grade 1 and the child is greater than 7 41036 $("[js-derogation-gradeone]").show(); 41037 } 41038 41039 }); 41040 41041 $("[js-kindergarten-sister]").on("click", function () { 41042 41043 if (parseInt($(this).val()) == 1) { // yes 41044 $("[js-kindergarten-sister-name]").show(); 41045 } 41046 if (parseInt($(this).val()) == 0) { // no 41047 $("[js-kindergarten-sister-name]").hide(); 41048 } 41049 41050 }); 41051 41052 $("[js-english-eligibility]").on("click", function () { 41053 41054 $("[js-english-eligibility-no]").hide(); 41055 $("[js-english-eligibility-yes]").hide(); 41056 41057 if (parseInt($(this).val()) == 1) { // yes 41058 $("[js-english-eligibility-yes]").show(); 41059 $(".form__group[data-step='2']").find("[js-next-step]").show(); 41060 } 41061 if (parseInt($(this).val()) == 0) { // no 41062 $("[js-english-eligibility-no]").show(); 41063 $(".form__group[data-step='2']").find("[js-next-step]").show(); 41064 } 41065 41066 }); 41067 41068 $("[js-assessment]").on("click", function () { 41069 41070 if (parseInt($(this).val()) == 1) { // yes 41071 $("[js-assement-yes]").show(); 41072 } 41073 if (parseInt($(this).val()) == 0) { // no 41074 $("[js-assement-yes]").hide(); 41075 } 41076 }); 41077 41078 $("[js-same-as-parent1]").on("click", function () { 41079 41080 $(this).parents("fieldset").find("input[type=text]").prop("disabled", false); 41081 if ($(this).prop("checked")) { 41082 $(this).parents("fieldset").find("input[type=text]").val(""); 41083 $(this).parents("fieldset").find("input[type=text]").prop("disabled", true); 41084 } 41085 41086 }); 41087 41088 var recaptchaTicked = false; 41089 $("[js-submit]").on("click", function (e) { 41090 41091 e.preventDefault(); 41092 41093 let $form = $(this).parents("form"); 41094 let captcha = $form.find("[js-google-captcha]"); 41095 captcha.attr("class", ""); 41096 41097 if (!recaptchaTicked) { 41098 captcha.addClass("field-validation-error--centered"); 41099 } 41100 else { 41101 captcha.addClass("field-validation-valid"); 41102 } 41103 41104 if (recaptchaTicked && $(".registration-form").valid()) { 41105 saveRegistrationForm() // save form to Agility 41106 .then(function (submission) { 41107 if (submission !== null) { 41108 // now post back to our controller in order for the webhook to happen 41109 $.post("/PreregistrationForm/ProcessPreregistration", submission, function (response) { 41110 if (!response.Success) { 41111 $("[js-error]").show(); 41112 } 41113 else { 41114 // hide form, show error message 41115 $("#registrationForm").hide(); 41116 $("[js-success]").show(); 41117 } 41118 }); 41119 } 41120 41121 }, function () { 41122 return null; 41123 }); 41124 } 41125 });
41126 41127 function recaptchaCallback() { 41128 recaptchaTicked = true; 41129 } 41130 41131 function saveRegistrationForm() { 41132 41133 var serialise = $(".registration-form").serializeArray(); 41134 var submission = { 41135 RecordTypeName: "RegistrationForm" 41136 }; 41137 41138 // apply fields. 41139 for (iii = 0; iii < serialise.length; iii += 1) { 41140 if (serialise[iii].name === "g-recaptcha-response") { 41141 submission["RecaptchResponse"] = "true"; 41142 } 41143 else { 41144 submission[serialise[iii].name] = serialise[iii].value; 41145 } 41146 } 41147 41148 // fix the date 41149 var dob = new Date($("[js-child-dob]").val()); 41150 submission["ChildDOB"] = dob.getFullYear() + "-" + (dob.getMonth() + 1) + "-" + dob.getDate(); 41151 41152 // fix the complete bool. 41153 submission["AttendSisterKindergarten"] = !!parseInt(submission["AttendSisterKindergarten"]); 41154 submission["EnglishEducationEligibility"] = !!parseInt(submission["EnglishEducationEligibility"]); 41155 submission["HasAssessment"] = !!parseInt(submission["HasAssessment"]); 41156 41157 return saveRecordToAgility(submission); 41158 } 41159 41160 $(document).ready(function () { 41161 // Adds the booleanrequired attribute defined in the Helpers folder. 41162 $.validator.unobtrusive.adapters.addBool("booleanrequired", "required"); 41163 }) 41164 41165 41166 return { 41167 RecaptchaCallback: recaptchaCallback 41168 }; 41169 41170 41171 function saveRecordToAgility(submission) { 41172 return new Promise(function (resolve, reject) { 41173 41174 Agility.UGC.API.SaveRecord(submission, function (data) { 41175 if (data.ResponseType != Agility.UGC.API.ResponseType.OK) { 41176 reject(null); 41177 } 41178 else 41179 { 41180 resolve(submission); 41181 } 41182 }); 41183 41184 41185 }); 41186 } 41187 41188 41189})(RegistrationForm, window.jQuery); 41190 41191function recaptchaCallbackConfactForm() { 41192 PRF.RecaptchaCallback(); 41193};
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.